fix: populate ldns submodule and add autotools to LDNS build stage
- Re-cloned zonemaster-ldns with --recurse-submodules so the bundled ldns C library source (including Changelog and configure.ac) is present - Added autoconf, automake, libtool to Dockerfile.backend ldns-build stage so libtoolize + autoreconf can generate ldns/configure during make Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
66
zonemaster-ldns/ldns/pcat/Makefile.in
Normal file
66
zonemaster-ldns/ldns/pcat/Makefile.in
Normal file
@@ -0,0 +1,66 @@
|
||||
# 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@
|
||||
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@ -Wall -I.
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
LDNSDIR= @LDNSDIR@
|
||||
|
||||
INSTALL = $(srcdir)/../install-sh
|
||||
|
||||
COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS)
|
||||
LINK = $(CC) $(CFLAGS) $(LDFLAGS)
|
||||
LIBS_STC = -lpcap $(LDNSDIR)/lib/libldns.a -lcrypto -ldl
|
||||
|
||||
HEADER = config.h
|
||||
|
||||
.PHONY: all clean realclean all-static
|
||||
|
||||
all: p
|
||||
|
||||
all-static: pcat-stc pcat-diff-stc pcat-print-stc
|
||||
|
||||
p: pcat pcat-diff pcat-print
|
||||
# strip pcat
|
||||
# strip pcat-diff
|
||||
# strip pcat-print
|
||||
|
||||
pcat: pcat.o getdelim.o
|
||||
$(LINK) -o $@ $+ $(LIBS)
|
||||
|
||||
pcat-diff: pcat-diff.o getdelim.o
|
||||
$(LINK) -o $@ $+ $(LIBS)
|
||||
|
||||
pcat-print: pcat-print.o getdelim.o
|
||||
$(LINK) -o $@ $+ $(LIBS)
|
||||
|
||||
pcat-stc: pcat.o getdelim.o
|
||||
$(LINK) -o $(@:-stc=) $+ $(LIBS_STC)
|
||||
|
||||
pcat-diff-stc: pcat-diff.o getdelim.o
|
||||
$(LINK) -o $(@:-stc=) $+ $(LIBS_STC)
|
||||
|
||||
pcat-print-stc: pcat-print.o getdelim.o
|
||||
$(LINK) -o $(@:-stc=) $+ $(LIBS_STC)
|
||||
|
||||
clean:
|
||||
rm -f pcat pcat-diff pcat-print
|
||||
rm -f pcat.o pcat-diff.o pcat-print.o
|
||||
|
||||
realclean: clean
|
||||
rm -f configure config.h config.log config.status
|
||||
|
||||
|
||||
## implicit rule
|
||||
%.o: $(srcdir)/%.c
|
||||
$(COMPILE) -c $<
|
||||
176
zonemaster-ldns/ldns/pcat/README.pcat
Normal file
176
zonemaster-ldns/ldns/pcat/README.pcat
Normal file
@@ -0,0 +1,176 @@
|
||||
PCAT README
|
||||
|
||||
PCAT -- cat pcap streams
|
||||
|
||||
1. Introduction
|
||||
Pcat consists out of three programs:
|
||||
1. pcat
|
||||
This program reads a raw pcap stream, extract the payload of
|
||||
each packet and sends the payload to a nameserver of the user's
|
||||
choice.
|
||||
Each payload and reply from the server is printed to standard
|
||||
output as ASCII. The binary packet/payload contents is printed
|
||||
as hexadecimal in network order.
|
||||
|
||||
2. pcat-diff
|
||||
This utility reads two streams/files as generated by 'pcat' it
|
||||
then compare these and prints the differences to standard
|
||||
output.
|
||||
|
||||
The output format is simular to that of 'pcat', and can be
|
||||
viewed with pcat-print.
|
||||
|
||||
Alternatively, pcat-diff can do advanced checking on differences,
|
||||
in which case the output will differ. See "Advanced Differences"
|
||||
for more on this.
|
||||
|
||||
3. pcat-print
|
||||
This program reads the 'diff' as printed by 'pcat-diff' and
|
||||
tries to re-generate to original DNS packets. If this succeeds
|
||||
the packet is printed to standard output. If it fails an error
|
||||
is printed instead.
|
||||
|
||||
4. pcat-grep.pl
|
||||
This is a small perl script that can 'grep' pcat streams. If you
|
||||
know for instance that query number 1023 doesn't match you can
|
||||
filter that query out by means of pcat-grep.pl
|
||||
|
||||
2. Format Used
|
||||
The format used is a simple line based ASCII format. Each "record"
|
||||
consists out of 4 lines. Empty lines are discarded. The format is
|
||||
specified as follows:
|
||||
1. sequence number
|
||||
2. hex dump
|
||||
3. hex dump
|
||||
4. hex dump or empty line
|
||||
|
||||
Each hex dump is a query in network order, printed as hexadecimal.
|
||||
|
||||
3. Usage
|
||||
All pcat utils are created as filters, thus they will read from a file
|
||||
or standard input. All output is send to standard output.
|
||||
|
||||
Send a steam to a nameserver:
|
||||
./pcat -a 213.154.224.1 20011009-134418-q50000.pkt > reply.53
|
||||
|
||||
Or print it directly:
|
||||
./pcat -a 213.154.224.1 20011009-134418-q50000.pkt | pcat-print
|
||||
|
||||
Send the stream to another nameserver:
|
||||
./pcat -a 213.154.224.1 -p 5454 20011009-134418-q50000.pkt > reply.5454
|
||||
|
||||
The two pcat-stream, 'reply.53' and 'reply.5454' can now be diffed with
|
||||
pcat-diff:
|
||||
./pcat-diff reply.53 reply.54 > reply.diff
|
||||
|
||||
If we to see what actual packets that differ (if they can be parsed) we
|
||||
can use pcap-print:
|
||||
pcap-print reply.diff
|
||||
|
||||
Or it can all be done with pipes, eliminating the need of files.
|
||||
./pcat-diff <(./pcat -a 213.154.224.1 20011009-134418-q50000.pkt) \
|
||||
<(./pcat 213.154.224.1 -p 5454 20011009-134418-q50000.pkt) | ./pcat-print
|
||||
|
||||
|
||||
4. Advanced differences
|
||||
|
||||
You can let pcat-diff do more intelligent checking on the differences between
|
||||
two outputs of pcat. In this mode, pcat-diff takes an argument specifying a
|
||||
directory containing files whose name end in .match. These files specify
|
||||
'Known' differences. It works like this:
|
||||
|
||||
If a difference between two answer packets is found, the packet is first
|
||||
normalized; the packet dates is changed to match, and each section is
|
||||
sorted. If these changes still don't make the packets equal, the
|
||||
match-specifications in the specified directory are consulted.
|
||||
|
||||
These specifications contain 3 elements; a 1-line description of the type of
|
||||
difference, a specification the question must match, and a specification
|
||||
that both answer packets must match.
|
||||
|
||||
The first line contains the specification, the following lines the
|
||||
specifications, separated by a line starting with an exclamation mark.
|
||||
|
||||
A specification looks like the normal output of drill and dig. It is based
|
||||
on the text representation format from the DNS RFCs. It can contain the
|
||||
following special characters:
|
||||
|
||||
* whitespace: whitespace is skipped and ignored
|
||||
* ?: Following a question mark, all characters up to the next
|
||||
whitespace are optional, so they can either exist or not in the answer
|
||||
* []: Square brackets contain a list of words/values of which exactly
|
||||
one must be present in the packets.
|
||||
* *: A star specifies that the packets may contain everything until it
|
||||
matches the next character in the specification. You can use
|
||||
multiple stars in a row, the number of stars specify the number of
|
||||
next characters that must match before continuing.
|
||||
* &: The ampersand works the same as the *, but in this case the value
|
||||
that matches must be exactly the same in both packets.
|
||||
|
||||
There are 2 special cases that can be used instead of a packet description:
|
||||
|
||||
* BADPACKET: if you use this as the complete description of the query
|
||||
packet, this matches any query that cannot be parsed
|
||||
* NOANSWER: if you use this as the complete description of the answer
|
||||
packet, this matches *both* packets if *one* had no answer
|
||||
(the other packet is ignored, if both packets had no answer,
|
||||
they were equal anyway)
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
Different additional section
|
||||
*
|
||||
!
|
||||
;; ->>HEADER<<- opcode: &, rcode: &, id: &
|
||||
;; flags: & ; QUERY: &, ANSWER: &, AUTHORITY: &, ADDITIONAL: &
|
||||
;; QUESTION SECTION:
|
||||
;; &&&&&
|
||||
|
||||
;; ANSWER SECTION:
|
||||
&&&&&
|
||||
|
||||
;; AUTHORITY SECTION:
|
||||
&&&&&
|
||||
|
||||
;; ADDITIONAL SECTION:
|
||||
*****
|
||||
|
||||
;; Query time: & msec
|
||||
&&&&&
|
||||
;; WHEN: &
|
||||
;; MSG SIZE rcvd: &
|
||||
|
||||
The description of this examples is 'Different additional section'.
|
||||
|
||||
The query specification contains only one *, so every query matches this.
|
||||
|
||||
The answer specification specifies that the packets must be completely
|
||||
equal, except for the additional part. The additional part must, however,
|
||||
contain an equal amount of entries (see the & after ADDITIONAL in line 2).
|
||||
|
||||
In the question section, 5 &'s are used, so that everything passes until the
|
||||
packets contain the text ';; AU'. This could of course be expanded to
|
||||
completely match the text ';; AUTHORITY SECTION', by using even more
|
||||
ampersands.
|
||||
|
||||
|
||||
If pcat-diff in advanced mode encounters a difference which is not known, it
|
||||
prints the index number, query, and both answers, and then quits. It is
|
||||
expected that the user studies the new and unexpected difference, captures
|
||||
it in a match specification, and runs pcat-diff again. To speed up the
|
||||
process of finding all differences, you can start from the index number that
|
||||
was printed by using the option -s <index>.
|
||||
|
||||
If you want to know a bit more about why the packets did not match, you can
|
||||
specify verbose mode with -v. It is not advisable to do this on the complete
|
||||
input, but rather use -s to start with the offending packet. Verbose mode
|
||||
produces a LOT of output.
|
||||
|
||||
If the complete files have been read, and no unknown differences have been
|
||||
found, statistics are printed about the known differences encountered.
|
||||
Because this can take a long time, you can use '-p <nr>' to print
|
||||
preliminary results every nr packets.
|
||||
|
||||
|
||||
|
||||
331
zonemaster-ldns/ldns/pcat/configure.ac
Normal file
331
zonemaster-ldns/ldns/pcat/configure.ac
Normal file
@@ -0,0 +1,331 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT(pcat, 1.7.0, dns-team@nlnetlabs.nl,pcat)
|
||||
AC_CONFIG_SRCDIR([pcat.c])
|
||||
|
||||
OURCPPFLAGS=''
|
||||
CPPFLAGS=${CPPFLAGS:-${OURCPPFLAGS}}
|
||||
OURCFLAGS='-g'
|
||||
CFLAGS=${CFLAGS:-${OURCFLAGS}}
|
||||
|
||||
AC_AIX
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_MAKE_SET
|
||||
|
||||
dnl routine to help check for compiler flags.
|
||||
AC_DEFUN([CHECK_COMPILER_FLAG],
|
||||
[
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING(whether $CC supports -$1)
|
||||
cache=`echo $1 | sed 'y%.=/+-%___p_%'`
|
||||
AC_CACHE_VAL(cv_prog_cc_flag_$cache,
|
||||
[
|
||||
echo 'void f(){}' >conftest.c
|
||||
if test -z "`$CC -$1 -c conftest.c 2>&1`"; then
|
||||
eval "cv_prog_cc_flag_$cache=yes"
|
||||
else
|
||||
eval "cv_prog_cc_flag_$cache=no"
|
||||
fi
|
||||
rm -f conftest*
|
||||
])
|
||||
if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
:
|
||||
$2
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
:
|
||||
$3
|
||||
fi
|
||||
])
|
||||
|
||||
dnl routine to help check for needed compiler flags.
|
||||
# if the given code compiles without the flag, execute argument 4
|
||||
# if the given code only compiles with the flag, execute argument 3
|
||||
# otherwise fail, execute argument 5.
|
||||
AC_DEFUN([CHECK_COMPILER_FLAG_NEEDED],
|
||||
[
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING(whether we need $1 as a flag for $CC)
|
||||
cache=`echo $1 | sed 'y%.=/+- %___p__%'`
|
||||
AC_CACHE_VAL(cv_prog_cc_flag_needed_$cache,
|
||||
[
|
||||
echo '$2' > conftest.c
|
||||
echo 'void f(){}' >>conftest.c
|
||||
if test -z "`$CC -Werror -Wall $CFLAGS -c conftest.c 2>&1`"; then
|
||||
eval "cv_prog_cc_flag_needed_$cache=no"
|
||||
else
|
||||
[
|
||||
if test -z "`$CC $1 -Werror -Wall $CFLAGS -c conftest.c 2>&1`"; then
|
||||
eval "cv_prog_cc_flag_needed_$cache=yes"
|
||||
else
|
||||
eval "cv_prog_cc_flag_needed_$cache=fail"
|
||||
#echo 'Test with flag fails too!'
|
||||
#cat conftest.c
|
||||
#echo "$CC $1 -Werror -Wall $CFLAGS -c conftest.c 2>&1"
|
||||
#echo `$CC $1 -Werror -Wall $CFLAGS -c conftest.c`
|
||||
#exit 1
|
||||
fi
|
||||
]
|
||||
fi
|
||||
rm -f conftest
|
||||
])
|
||||
if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
:
|
||||
$3
|
||||
else
|
||||
if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
:
|
||||
$4
|
||||
else
|
||||
AC_MSG_RESULT(failed)
|
||||
:
|
||||
#cat conftest.c
|
||||
#echo "$CC -Werror -Wall $CFLAGS -c conftest.c"
|
||||
#echo `$CC -Werror -Wall $CFLAGS -c conftest.c`
|
||||
#echo "$CC $1 -Werror -Wall $CFLAGS -c conftest.c"
|
||||
#echo `$CC $1 -Werror -Wall $CFLAGS -c conftest.c`
|
||||
$5
|
||||
|
||||
fi
|
||||
fi
|
||||
])
|
||||
CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
|
||||
|
||||
CHECK_COMPILER_FLAG(std=c99, [C99FLAG="-std=c99"])
|
||||
CHECK_COMPILER_FLAG(xc99, [C99FLAG="-xc99"])
|
||||
|
||||
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"])
|
||||
|
||||
CHECK_COMPILER_FLAG_NEEDED($C99FLAG,
|
||||
[
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
int test() {
|
||||
int a = 0;
|
||||
a = isblank(12);
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS $C99FLAG"])
|
||||
|
||||
CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE,
|
||||
[
|
||||
#include <ctype.h>
|
||||
|
||||
int test() {
|
||||
int a;
|
||||
a = isascii(32);
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS -D_BSD_SOURCE"])
|
||||
|
||||
CHECK_COMPILER_FLAG_NEEDED(-D_POSIX_C_SOURCE=200112,
|
||||
[
|
||||
#include <time.h>
|
||||
|
||||
int test() {
|
||||
int a = 0;
|
||||
char *t;
|
||||
time_t time = 0;
|
||||
char *buf = NULL;
|
||||
t = ctime_r(&time, buf);
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=200112"])
|
||||
|
||||
CHECK_COMPILER_FLAG_NEEDED(-D__EXTENSIONS__,
|
||||
[
|
||||
#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;
|
||||
tv.tv_usec = 10;
|
||||
srandom(32);
|
||||
#ifdef HAVE_GETOPT_H
|
||||
a = getopt(2, opts, "a");
|
||||
#else
|
||||
opts = opts;
|
||||
#endif
|
||||
a = isascii(32);
|
||||
return a;
|
||||
}
|
||||
], [CFLAGS="$CFLAGS -D__EXTENSIONS__"])
|
||||
|
||||
|
||||
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],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([netinet/in_systm.h net/if.h netinet/ip.h netinet/udp.h netinet/if_ether.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])
|
||||
|
||||
AC_CHECK_HEADERS([sys/param.h sys/mount.h],,,
|
||||
[AC_INCLUDES_DEFAULT]
|
||||
[
|
||||
[
|
||||
#if HAVE_SYS_PARAM_H
|
||||
# include <sys/param.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="$LDFLAGS -L$withval/lib"
|
||||
]
|
||||
)
|
||||
|
||||
# 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="$LDFLAGS -L$ldns_dev_dir/lib"
|
||||
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)
|
||||
|
||||
AC_CHECK_HEADER(ldns/ldns.h,, [
|
||||
AC_MSG_ERROR([Can't find ldns headers])
|
||||
], [AC_INCLUDES_DEFAULT]
|
||||
)
|
||||
|
||||
AC_CHECK_LIB(pcap, pcap_open_offline,, [
|
||||
AC_MSG_ERROR([Can't find pcap library.])
|
||||
]
|
||||
)
|
||||
|
||||
AC_CHECK_FUNCS(getdelim)
|
||||
AC_CHECK_FUNCS(isblank)
|
||||
AC_CHECK_FUNCS(strndup)
|
||||
|
||||
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
|
||||
])
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AC_OUTPUT
|
||||
63
zonemaster-ldns/ldns/pcat/getdelim.c
Normal file
63
zonemaster-ldns/ldns/pcat/getdelim.c
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "config.h"
|
||||
#ifndef HAVE_GETDELIM
|
||||
|
||||
#define GETDELIM_BUFFER 128
|
||||
|
||||
/* copied from xine-devel */
|
||||
size_t
|
||||
getdelim( char **lineptr, size_t *n, int delimiter, FILE *stream )
|
||||
{
|
||||
char *p;
|
||||
int c;
|
||||
size_t len = 0;
|
||||
|
||||
if (!lineptr || !n || (!*lineptr && *n))
|
||||
return -1;
|
||||
|
||||
/* allocate initial buffer */
|
||||
if (!*lineptr || !*n) {
|
||||
char *np;
|
||||
np = realloc( *lineptr, GETDELIM_BUFFER );
|
||||
if (!np)
|
||||
return -1;
|
||||
*n = GETDELIM_BUFFER;
|
||||
*lineptr = np;
|
||||
}
|
||||
|
||||
p = *lineptr;
|
||||
|
||||
/* read characters from stream */
|
||||
while ((c = fgetc( stream )) != EOF) {
|
||||
if (len >= *n) {
|
||||
char *np = realloc( *lineptr, *n * 2 );
|
||||
if (!np)
|
||||
return -1;
|
||||
p = np + (p - *lineptr);
|
||||
*lineptr = np;
|
||||
*n *= 2;
|
||||
}
|
||||
*p++ = (char) c;
|
||||
len++;
|
||||
if (delimiter == c)
|
||||
break;
|
||||
}
|
||||
|
||||
/* end of file without any bytes read */
|
||||
if ((c == EOF) && (len == 0))
|
||||
return -1;
|
||||
|
||||
/* trailing "\0" */
|
||||
if (len >= *n) {
|
||||
char *np = realloc( *lineptr, *n + 1 );
|
||||
if (!np)
|
||||
return -1;
|
||||
p = np + (p - *lineptr);
|
||||
*lineptr = np;
|
||||
*n += 1;
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif /* !HAVE_GETDELIM */
|
||||
184
zonemaster-ldns/ldns/pcat/pcat-diff.1
Normal file
184
zonemaster-ldns/ldns/pcat/pcat-diff.1
Normal file
@@ -0,0 +1,184 @@
|
||||
'\" t
|
||||
.TH PCAT-DIFF 1 "08 Mar 2006" "pcat utils"
|
||||
.SH NAME
|
||||
pcat-diff \- show the difference between two pcat files.
|
||||
.SH SYNOPSIS
|
||||
.B pcat-diff
|
||||
.IR PCAT_FILE1
|
||||
.IR PCAT_FILE2
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBpcat-diff\fR reads in two pcat files and show the differences
|
||||
between them.
|
||||
Its output is another pcat stream which can then be interpreted by
|
||||
pcat-print.
|
||||
|
||||
pcat-diff can also do advanced checking against a number of specification,
|
||||
for instance to count the number of known differences between two
|
||||
implementations.
|
||||
|
||||
You can let pcat-diff do more intelligent checking on the differences between
|
||||
two outputs of pcat. In this mode, pcat-diff takes an argument specifying a
|
||||
directory containing files whose name end in .match. These files specify
|
||||
'Known' differences. It works like this:
|
||||
|
||||
If a difference between two answer packets is found, the packet is first
|
||||
normalized; the packet dates is changed to match, and each section is
|
||||
sorted. If these changes still don't make the packets equal, the
|
||||
match-specifications in the specified directory are consulted.
|
||||
|
||||
These specifications contain 3 elements; a 1-line description of the type of
|
||||
difference, a specification the question must match, and a specification
|
||||
that both answer packets must match.
|
||||
|
||||
The first line contains the specification, the following lines the
|
||||
specifications, separated by a line starting with an exclamation mark.
|
||||
|
||||
A specification looks like the normal output of drill and dig. It is based
|
||||
on the text representation format from the DNS RFCs. It can contain the
|
||||
following special characters:
|
||||
|
||||
* whitespace: whitespace is skipped and ignored
|
||||
* ?: Following a question mark, all characters up to the
|
||||
next whitespace are optional, so they can either
|
||||
exist or not in the answer
|
||||
* []: Square brackets contain a list of words/values of
|
||||
which exactly one must be present in the packets.
|
||||
* *: A star specifies that the packets may contain
|
||||
everything until it matches the next character in
|
||||
the specification. You can use multiple stars in a
|
||||
row, the number of stars specify the number of next
|
||||
characters that must match before continuing.
|
||||
* &: The ampersand works the same as the *, but in this
|
||||
case the value that matches must be exactly the
|
||||
same in both packets.
|
||||
|
||||
There are 2 special cases that can be used instead of a packet description:
|
||||
|
||||
* BADPACKET: if you use this as the complete description
|
||||
of the query packet, this matches any query
|
||||
that cannot be parsed
|
||||
* NOANSWER: if you use this as the complete description
|
||||
of the answer packet, this matches *both*
|
||||
packets if *one* had no answer (the other
|
||||
packet is ignored, if both packets had no
|
||||
answer, they were equal anyway)
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
Different additional section
|
||||
*
|
||||
!
|
||||
;; ->>HEADER<<- opcode: &, rcode: &, id: &
|
||||
;; flags: & ; QUERY: &, ANSWER: &, AUTHORITY: &, ADDITIONAL: &
|
||||
;; QUESTION SECTION:
|
||||
;; &&&&&
|
||||
|
||||
;; ANSWER SECTION:
|
||||
&&&&&
|
||||
|
||||
;; AUTHORITY SECTION:
|
||||
&&&&&
|
||||
|
||||
;; ADDITIONAL SECTION:
|
||||
*****
|
||||
|
||||
;; Query time: & msec
|
||||
&&&&&
|
||||
;; WHEN: &
|
||||
;; MSG SIZE rcvd: &
|
||||
|
||||
The description of this examples is 'Different additional section'.
|
||||
|
||||
The query specification contains only one *, so every query matches this.
|
||||
|
||||
The answer specification specifies that the packets must be completely
|
||||
equal, except for the additional part. The additional part must, however,
|
||||
contain an equal amount of entries (see the & after ADDITIONAL in line 2).
|
||||
|
||||
In the question section, 5 &'s are used, so that everything passes until the
|
||||
packets contain the text ';; AU'. This could of course be expanded to
|
||||
completely match the text ';; AUTHORITY SECTION', by using even more
|
||||
ampersands.
|
||||
|
||||
|
||||
If pcat-diff in advanced mode encounters a difference which is not known, it
|
||||
prints the index number, query, and both answers, and then quits. It is
|
||||
expected that the user studies the new and unexpected difference, captures
|
||||
it in a match specification, and runs pcat-diff again. To speed up the
|
||||
process of finding all differences, you can start from the index number that
|
||||
was printed by using the option -s <index>.
|
||||
|
||||
If you want to know a bit more about why the packets did not match, you can
|
||||
specify verbose mode with -v. It is not advisable to do this on the complete
|
||||
input, but rather use -s to start with the offending packet. Verbose mode
|
||||
produces a LOT of output.
|
||||
|
||||
If the complete files have been read, and no unknown differences have been
|
||||
found, statistics are printed about the known differences encountered.
|
||||
Because this can take a long time, you can use '-p <nr>' to print
|
||||
preliminary results every nr packets.
|
||||
|
||||
|
||||
.PP
|
||||
If PCAT_FILE2 is not given, standard input is read.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB-d\fR \fIdirectory\fR
|
||||
Directory containing match files, this options sets the advanced checking mode, see manpage
|
||||
|
||||
.TP
|
||||
\fB-h\fR
|
||||
Show usage
|
||||
|
||||
.TP
|
||||
\fB-m\fR \fInumber\fR
|
||||
only check up to <number> packets
|
||||
|
||||
.TP
|
||||
\fB-o\fR
|
||||
show original packets when printing diffs (by default, packets are normalized)
|
||||
|
||||
.TP
|
||||
\fB-p\fR \fInumber\fR
|
||||
show intermediate results every <number> packets
|
||||
|
||||
.TP
|
||||
\fB-s\fR \fInumber\fR
|
||||
only start checking after <number> packets
|
||||
|
||||
.TP
|
||||
\fB-v\fR
|
||||
verbose mode
|
||||
|
||||
|
||||
.SH OUTPUT FORMAT
|
||||
The default output of \fBpcat-diff\fR consists "records". Each record has four lines:
|
||||
.PP
|
||||
1. xxx - (decimal) sequence number
|
||||
2. hex dump - query in hex, network order
|
||||
3. hex dump - answer of FILE1 in hex, network order
|
||||
4. hex dump - answer of FILE2 in hex, network order.
|
||||
|
||||
The advanced output only prints statistics about the types of differences
|
||||
found and their percentages. If an unknown difference is found it prints
|
||||
the relevant packets and exits.
|
||||
|
||||
|
||||
.SH ALSO SEE
|
||||
Also see pcat(1) and pcat-print(1).
|
||||
|
||||
.SH AUTHOR
|
||||
Written by Miek Gieben for NLnet Labs.
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Report bugs to <dns-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.
|
||||
.PP
|
||||
Licensed under the BSD License.
|
||||
1448
zonemaster-ldns/ldns/pcat/pcat-diff.c
Normal file
1448
zonemaster-ldns/ldns/pcat/pcat-diff.c
Normal file
File diff suppressed because it is too large
Load Diff
75
zonemaster-ldns/ldns/pcat/pcat-grep.pl
Executable file
75
zonemaster-ldns/ldns/pcat/pcat-grep.pl
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# take a numerical range and ranges and
|
||||
# only show those ranges or not (-v)
|
||||
# single numbers: 4
|
||||
# ranges: 5-10 (inclusive)
|
||||
# separated by comma's
|
||||
# -v reverse
|
||||
|
||||
use strict;
|
||||
|
||||
my %numbers = ();
|
||||
my $reverse = 0;
|
||||
my $i;
|
||||
my $k;
|
||||
|
||||
foreach my $r (@ARGV) {
|
||||
|
||||
if ($r eq "-v") {
|
||||
$reverse = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
if ($r =~ /-/) {
|
||||
my ($s, $e) = split /-/, $r;
|
||||
|
||||
if ($s > $e) {
|
||||
next;
|
||||
}
|
||||
|
||||
for ($i = $s; $i <= $e; $i++) {
|
||||
$numbers{$i} = 1;
|
||||
}
|
||||
next;
|
||||
}
|
||||
$numbers{$r} = 1;
|
||||
}
|
||||
|
||||
# read in the input, pcat style
|
||||
my $line; my $left; my $right;
|
||||
$i = 1;
|
||||
my $print = 0;
|
||||
while(<STDIN>) {
|
||||
if ($i % 4 == 1) {
|
||||
s/^q: //; # kill it, if we do query diff
|
||||
|
||||
($left, $right) = split /:/, $_;
|
||||
foreach $k (keys %numbers) {
|
||||
if ($k == $left) {
|
||||
if ($reverse == 1) {
|
||||
$print = 0;
|
||||
} else {
|
||||
$print = 1;
|
||||
}
|
||||
last;
|
||||
}
|
||||
if ($reverse == 1) {
|
||||
$print = 1;
|
||||
} else {
|
||||
$print = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($print == 1) {
|
||||
print $_;
|
||||
}
|
||||
if ($i % 4 == 0) {
|
||||
if ($reverse == 1) {
|
||||
$print = 1;
|
||||
} else {
|
||||
$print = 0;
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
64
zonemaster-ldns/ldns/pcat/pcat-print.1
Normal file
64
zonemaster-ldns/ldns/pcat/pcat-print.1
Normal file
@@ -0,0 +1,64 @@
|
||||
'\" t
|
||||
.TH PCAT-PRINT 1 "08 Mar 2006" "pcat utils"
|
||||
.SH NAME
|
||||
pcat-print \- reformat hexadecimal packets back to dig-like syntax
|
||||
.SH SYNOPSIS
|
||||
.B pcat-printp
|
||||
[
|
||||
.IR \-h
|
||||
]
|
||||
.IR PCAT_STREAM
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBpcat-print\fR reads in a pcat file and reformats the hexadecimal
|
||||
packets back into a dig-like syntax. If a packet cannot be transformed
|
||||
back into a sane syntax an error is emitted.
|
||||
|
||||
This makes the manual inspection of the packets easier.
|
||||
|
||||
.PP
|
||||
If no pcat file is given, standard input is read.
|
||||
|
||||
.SH OPTIONS
|
||||
There are no options. Like \fBpcat-diff\fR this utility always does
|
||||
what you want.
|
||||
|
||||
.SH OUTPUT FORMAT
|
||||
\fBpcat-print\fR will output records.
|
||||
Each record consists of an index and then three packets.
|
||||
Each packet is separated by a line of '='s. All in all the output looks
|
||||
like:
|
||||
|
||||
==========================
|
||||
==========================
|
||||
Index: xxx:yyy
|
||||
==========================
|
||||
query packet
|
||||
==========================
|
||||
first answer/query packet
|
||||
==========================
|
||||
second answer/query packet
|
||||
==========================
|
||||
.PP
|
||||
For the index: xxx:yyy. xxx is the query ID of the first answer/query and
|
||||
yyy is the query ID of the second one. These two IDs should match. The query
|
||||
ID of the query packet is also equal to xxx.
|
||||
|
||||
.SH ALSO SEE
|
||||
Also see pcat(1) and pcat-diff(1).
|
||||
|
||||
.SH AUTHOR
|
||||
Written by Miek Gieben for NLnet Labs.
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Report bugs to <dns-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.
|
||||
.PP
|
||||
Licensed under the BSD License.
|
||||
|
||||
|
||||
|
||||
88
zonemaster-ldns/ldns/pcat/pcat-print.c
Normal file
88
zonemaster-ldns/ldns/pcat/pcat-print.c
Normal file
@@ -0,0 +1,88 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
#define SEQUENCE 1
|
||||
#define QUERY 2
|
||||
#define ANSWER1 3
|
||||
#define ANSWER2 0
|
||||
#define LINES 4
|
||||
|
||||
#ifndef HAVE_GETDELIM
|
||||
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
|
||||
#endif
|
||||
|
||||
void
|
||||
printf_bar(void)
|
||||
{
|
||||
fprintf(stdout, "===================================================================\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
ssize_t read;
|
||||
char *line;
|
||||
size_t i, j, k, len;
|
||||
u_char pkt_buf[LDNS_MAX_PACKETLEN];
|
||||
ldns_pkt *p;
|
||||
ldns_status s;
|
||||
FILE *diff = stdin;
|
||||
|
||||
i = 1;
|
||||
len = 0;
|
||||
line = NULL;
|
||||
|
||||
if (argc > 1) {
|
||||
if (!(diff = fopen(argv[1], "r"))) {
|
||||
fprintf(stderr, "Cannot open pcat diff file `%s\'\n", argv[1]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
while((read = getdelim(&line, &len, '\n', diff)) != -1) {
|
||||
if (read < 2 || read > LDNS_MAX_PACKETLEN) {
|
||||
if(read == 1)
|
||||
fprintf(stdout, "NO ANSWER (line %d)\n", (int)i);
|
||||
else
|
||||
fprintf(stdout, "Under- or overflow (%d) - "
|
||||
"skipping line %d\n", (int)read, (int)i);
|
||||
i++;
|
||||
printf_bar();
|
||||
continue;
|
||||
}
|
||||
|
||||
line[read - 1] = '\0';
|
||||
switch(i % LINES) {
|
||||
case SEQUENCE:
|
||||
printf_bar();
|
||||
fprintf(stdout, "Index: %s\n", line);
|
||||
printf_bar();
|
||||
break;
|
||||
case QUERY:
|
||||
case ANSWER1:
|
||||
case ANSWER2:
|
||||
k = 0;
|
||||
for(j = 0; j < read - 1; j += 2) {
|
||||
pkt_buf[k] =
|
||||
ldns_hexdigit_to_int(line[j]) * 16 +
|
||||
ldns_hexdigit_to_int(line[j + 1]);
|
||||
k++;
|
||||
}
|
||||
s = ldns_wire2pkt(&p, pkt_buf, k);
|
||||
fprintf(stdout, "=* %s\n", line);
|
||||
if (s != LDNS_STATUS_OK) {
|
||||
fprintf(stdout, "%s\n", ldns_get_errorstr_by_id(s));
|
||||
} else {
|
||||
ldns_pkt_print(stdout, p);
|
||||
}
|
||||
printf_bar();
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
len = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
59
zonemaster-ldns/ldns/pcat/pcat.1
Normal file
59
zonemaster-ldns/ldns/pcat/pcat.1
Normal file
@@ -0,0 +1,59 @@
|
||||
'\" t
|
||||
.TH PCAT 1 "08 Mar 2006" "pcat utils"
|
||||
.SH NAME
|
||||
pcat \- (re)-send a pcap trace to a nameserver
|
||||
.SH SYNOPSIS
|
||||
.B pcat
|
||||
[
|
||||
.IR \-a
|
||||
IP
|
||||
]
|
||||
[
|
||||
.IR \-p
|
||||
PORT
|
||||
]
|
||||
.IR PCAP_STRACE
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBpcat\fR reads in a pcap trace file and re-sends the packet's payload
|
||||
to a nameserver. It prints each query and the reply to standard output
|
||||
is a hexadecimal format.
|
||||
.PP
|
||||
If no pcap file is given, standard input is read.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-a IP
|
||||
Use IP as address to send the queries to.
|
||||
.TP
|
||||
.B \-p PORT
|
||||
Use PORT as port number.
|
||||
|
||||
.SH OUTPUT FORMAT
|
||||
The output of \fBpcat\fR consists "records". Each record has four lines:
|
||||
.PP
|
||||
1. xxx - (decimal) sequence number
|
||||
2. hex dump - query in hex, network order
|
||||
3. hex dump - answer in hex, network order
|
||||
4. empty line
|
||||
|
||||
The reason for the fourth line is that \fBpcat-print\fR can now parse
|
||||
both \fBpcat\fRs and \fBpcat-diff\fRs output.
|
||||
.PP
|
||||
This format is dubbed: \fBpcat\fR.
|
||||
|
||||
.SH ALSO SEE
|
||||
Also see pcat-print(1) and pcat-diff(1).
|
||||
|
||||
.SH AUTHOR
|
||||
Written by Miek Gieben for NLnet Labs.
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Report bugs to <dns-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.
|
||||
.PP
|
||||
Licensed under the BSD License.
|
||||
311
zonemaster-ldns/ldns/pcat/pcat.c
Normal file
311
zonemaster-ldns/ldns/pcat/pcat.c
Normal file
@@ -0,0 +1,311 @@
|
||||
#ifdef HAVE_GETDELIM
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#ifdef HAVE_GETOPT_H
|
||||
# include <getopt.h>
|
||||
#endif
|
||||
|
||||
#include <ldns/ldns.h>
|
||||
#include <errno.h>
|
||||
#include <pcap.h>
|
||||
|
||||
#define FAILURE 10000
|
||||
|
||||
|
||||
#ifndef ETHERTYPE_IPV6
|
||||
#define ETHERTYPE_IPV6 0x86dd
|
||||
#endif
|
||||
#define DNS_UDP_OFFSET 42
|
||||
|
||||
#ifndef HAVE_GETDELIM
|
||||
size_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
|
||||
#endif
|
||||
|
||||
/* output: see usage() */
|
||||
|
||||
void
|
||||
usage(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "pcat [-a IP] [-p PORT] [-r] PCAP_FILE\n\n");
|
||||
fprintf(fp, " -a IP\tuse IP as nameserver, defaults to 127.0.0.1\n");
|
||||
fprintf(fp, " -p PORT\tuse PORT as port, defaults to 53\n");
|
||||
fprintf(fp, " -r \t\tthe file is a pcat output file to resend queries from\n");
|
||||
fprintf(fp, " -h \t\tthis help\n");
|
||||
fprintf(fp, " PCAP_FILE\tuse this file as source\n");
|
||||
fprintf(fp, " If no file is given standard input is read\n");
|
||||
fprintf(fp, "\nOUTPUT FORMAT:\n");
|
||||
fprintf(fp, " Line based output format, each record consists of 3 lines:\n");
|
||||
fprintf(fp, " 1. xxx\t\tdecimal sequence number\n");
|
||||
fprintf(fp, " 2. hex dump\t\tquery in hex, network order\n");
|
||||
fprintf(fp, " 3. hex dump\t\tanswer in hex, network order\n");
|
||||
fprintf(fp, " 4. empty line\n");
|
||||
fprintf(fp, " The reason for 4. is that pcat-print now can be used on the output of pcat.\n");
|
||||
}
|
||||
|
||||
void
|
||||
data2hex(FILE *fp, u_char *p, size_t l)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < l; i++) {
|
||||
fprintf(fp, "%02x", (unsigned int) p[i]);
|
||||
}
|
||||
fputs("\n", fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a hex string to binary data
|
||||
* len is the length of the string
|
||||
* buf is the buffer to store the result in
|
||||
* offset is the starting position in the result buffer
|
||||
*
|
||||
* 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");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bufpos;
|
||||
}
|
||||
|
||||
u_char *
|
||||
pcap2ldns_pkt_ip(const u_char *packet, struct pcap_pkthdr *h)
|
||||
{
|
||||
h->caplen -= DNS_UDP_OFFSET;
|
||||
if (h->caplen < 0) {
|
||||
return NULL;
|
||||
} else {
|
||||
return (u_char*)(packet + DNS_UDP_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
u_char *
|
||||
pcap2ldns_pkt(const u_char *packet, struct pcap_pkthdr *h)
|
||||
{
|
||||
struct ether_header *eptr;
|
||||
|
||||
eptr = (struct ether_header *) h;
|
||||
switch(eptr->ether_type) {
|
||||
case ETHERTYPE_IP:
|
||||
return pcap2ldns_pkt_ip(packet, h);
|
||||
break;
|
||||
case ETHERTYPE_IPV6:
|
||||
break;
|
||||
case ETHERTYPE_ARP:
|
||||
fprintf(stderr, "ARP pkt, dropping\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Not IP pkt, dropping\n");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
pcap_t *p = NULL;
|
||||
struct pcap_pkthdr h;
|
||||
const u_char *x;
|
||||
size_t i = 0;
|
||||
ldns_rdf *ip;
|
||||
char *ip_str;
|
||||
int c;
|
||||
size_t failure;
|
||||
FILE *infile = NULL;
|
||||
int pcat_input_file = 0;
|
||||
|
||||
uint8_t *result;
|
||||
uint16_t port;
|
||||
ldns_buffer *qpkt;
|
||||
u_char *q;
|
||||
size_t size;
|
||||
socklen_t tolen;
|
||||
size_t query_pkt_len;
|
||||
|
||||
struct timeval timeout;
|
||||
struct sockaddr_storage *data;
|
||||
struct sockaddr_in *data_in;
|
||||
|
||||
ldns_status send_status;
|
||||
|
||||
port = 0;
|
||||
ip = NULL;
|
||||
ip_str = NULL;
|
||||
failure = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, "ha:p:r")) != -1) {
|
||||
switch(c) {
|
||||
case 'h':
|
||||
usage(stdout);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'a':
|
||||
ip_str = optarg;
|
||||
ip = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, optarg);
|
||||
if (!ip) {
|
||||
fprintf(stderr, "-a requires an IP address\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
pcat_input_file = 1;
|
||||
break;
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
if (port == 0) {
|
||||
fprintf(stderr, "-p requires a port number\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(stdout);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (port == 0)
|
||||
port = 53;
|
||||
|
||||
if (!ip) {
|
||||
ip_str = "127.0.0.1";
|
||||
ip = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1");
|
||||
}
|
||||
|
||||
if (pcat_input_file) {
|
||||
if (argc < 1) {
|
||||
infile = fopen("/dev/stdin", "r");
|
||||
} else {
|
||||
infile = fopen(argv[0], "r");
|
||||
}
|
||||
if (!infile) {
|
||||
fprintf(stderr, "Cannot open input file: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
if (argc < 1) {
|
||||
/* no file given - use standard input */
|
||||
p = pcap_open_offline("/dev/stdin", errbuf);
|
||||
} else {
|
||||
p = pcap_open_offline(argv[0], errbuf);
|
||||
}
|
||||
if (!p) {
|
||||
fprintf(stderr, "Cannot open pcap lib %s\n", errbuf);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
qpkt = ldns_buffer_new(LDNS_MAX_PACKETLEN);
|
||||
data = LDNS_MALLOC(struct sockaddr_storage);
|
||||
timeout.tv_sec = 5;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
/* setup the socket */
|
||||
data->ss_family = AF_INET;
|
||||
data_in = (struct sockaddr_in*) data;
|
||||
data_in->sin_port = (in_port_t)htons(port);
|
||||
memcpy(&(data_in->sin_addr), ldns_rdf_data(ip), ldns_rdf_size(ip));
|
||||
tolen = sizeof(struct sockaddr_in);
|
||||
|
||||
i = 1; /* start counting at 1 */
|
||||
while (1) {
|
||||
if(pcat_input_file) {
|
||||
/* read pcat format and repeat query in it */
|
||||
char buf[65535*2+100];
|
||||
uint8_t decoded[65535+100];
|
||||
if(!fgets(buf, sizeof(buf), infile)) /* number */
|
||||
break;
|
||||
if(!fgets(buf, sizeof(buf), infile)) /* query */
|
||||
break;
|
||||
query_pkt_len = hexstr2bin(buf, strlen(buf)&0xfffffffe,
|
||||
decoded, 0, sizeof(decoded));
|
||||
ldns_buffer_write(qpkt, decoded, query_pkt_len);
|
||||
|
||||
if(!fgets(buf, sizeof(buf), infile)) /* answer */
|
||||
break;
|
||||
if(!fgets(buf, sizeof(buf), infile)) /* empty line */
|
||||
break;
|
||||
} else {
|
||||
if(!(x = pcap_next(p, &h)))
|
||||
break;
|
||||
q = pcap2ldns_pkt_ip(x, &h);
|
||||
ldns_buffer_write(qpkt, q, h.caplen);
|
||||
query_pkt_len = h.caplen;
|
||||
}
|
||||
|
||||
send_status =ldns_udp_send(&result, qpkt, data, tolen, timeout, &size);
|
||||
if (send_status == LDNS_STATUS_OK) {
|
||||
/* double check if we are dealing with correct replies
|
||||
* by converting to a pkt... todo */
|
||||
fprintf(stdout, "%d\n", (int)i);
|
||||
/* query */
|
||||
data2hex(stdout, ldns_buffer_begin(qpkt), query_pkt_len);
|
||||
/* answer */
|
||||
data2hex(stdout, result, size);
|
||||
fflush(stdout);
|
||||
} else {
|
||||
/* todo print failure */
|
||||
failure++;
|
||||
fprintf(stderr, "Failure to send packet %u (attempt %u, error %s)\n", i, (unsigned int) failure, ldns_get_errorstr_by_id(send_status));
|
||||
fprintf(stdout, "%d\n", (int)i);
|
||||
/* query */
|
||||
data2hex(stdout, ldns_buffer_begin(qpkt), query_pkt_len);
|
||||
/* answer, thus empty */
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
fputs("\n", stdout);
|
||||
ldns_buffer_clear(qpkt);
|
||||
i++;
|
||||
if (failure > FAILURE) {
|
||||
fprintf(stderr, "More than %u failures, bailing out\n", FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if(pcat_input_file)
|
||||
fclose(infile);
|
||||
else pcap_close(p);
|
||||
return 0;
|
||||
}
|
||||
11
zonemaster-ldns/ldns/pcat/todo
Normal file
11
zonemaster-ldns/ldns/pcat/todo
Normal file
@@ -0,0 +1,11 @@
|
||||
maxpacketlen? We're are dealing with hex so it should prob. be
|
||||
twice as large?
|
||||
|
||||
ipv6
|
||||
|
||||
tcp packets
|
||||
|
||||
better pcap payload inspection - currently it only works for udp,
|
||||
ethernet
|
||||
|
||||
a speed setting to send queries faster?
|
||||
Reference in New Issue
Block a user