Merging upstream version 1.2.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
9ce9cc1418
commit
cc381791fc
340 changed files with 71346 additions and 6734 deletions
|
@ -24,11 +24,11 @@ SUBDIRS = test
|
|||
AM_CFLAGS = -Werror=attributes \
|
||||
-I$(srcdir) \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/include \
|
||||
$(SIMD_FLAGS) $(CPUEXT_FLAGS) \
|
||||
$(PTHREAD_CFLAGS) \
|
||||
$(luajit_CFLAGS) \
|
||||
$(libuv_CFLAGS) \
|
||||
$(libnghttp2_CFLAGS)
|
||||
$(liblz4_CFLAGS) $(libzstd_CFLAGS)
|
||||
|
||||
EXTRA_DIST = gen-manpage.lua gen-compat.lua gen-errno.sh dnsjit.1in
|
||||
|
||||
|
@ -37,23 +37,24 @@ BUILT_SOURCES = core/compat.hh core/log_errstr.c
|
|||
bin_PROGRAMS = dnsjit
|
||||
|
||||
dnsjit_SOURCES = dnsjit.c globals.c
|
||||
dist_dnsjit_SOURCES = core.lua lib.lua input.lua filter.lua globals.h \
|
||||
output.lua
|
||||
dist_dnsjit_SOURCES = core.lua lib.lua input.lua filter.lua output.lua
|
||||
dnsjitincludedir = $(includedir)/dnsjit
|
||||
nobase_dnsjitinclude_HEADERS = globals.h version.h
|
||||
lua_hobjects = core/compat.luaho
|
||||
lua_objects = core.luao lib.luao input.luao filter.luao output.luao
|
||||
dnsjit_LDADD = $(PTHREAD_LIBS) $(luajit_LIBS) $(libuv_LIBS) $(libnghttp2_LIBS)
|
||||
dnsjit_LDADD = $(PTHREAD_LIBS) $(luajit_LIBS) $(liblz4_LIBS) $(libzstd_LIBS)
|
||||
|
||||
# C source and headers
|
||||
dnsjit_SOURCES += core/channel.c core/compat.c core/log.c core/object.c core/object/dns.c core/object/ether.c core/object/gre.c core/object/icmp6.c core/object/icmp.c core/object/ieee802.c core/object/ip6.c core/object/ip.c core/object/linuxsll.c core/object/loop.c core/object/null.c core/object/payload.c core/object/pcap.c core/object/tcp.c core/object/udp.c core/producer.c core/receiver.c core/thread.c filter/copy.c filter/ipsplit.c filter/layer.c filter/split.c filter/timing.c input/fpcap.c input/mmpcap.c input/pcap.c input/zero.c lib/base64url.c lib/clock.c lib/trie.c output/dnscli.c output/dnssim.c output/dnssim/common.c output/dnssim/connection.c output/dnssim/https2.c output/dnssim/tcp.c output/dnssim/tls.c output/dnssim/udp.c output/null.c output/pcap.c output/respdiff.c output/tcpcli.c output/tlscli.c output/udpcli.c
|
||||
dist_dnsjit_SOURCES += core/assert.h core/channel.h core/compat.h core/log.h core/object/dns.h core/object/ether.h core/object/gre.h core/object.h core/object/icmp6.h core/object/icmp.h core/object/ieee802.h core/object/ip6.h core/object/ip.h core/object/linuxsll.h core/object/loop.h core/object/null.h core/object/payload.h core/object/pcap.h core/object/tcp.h core/object/udp.h core/producer.h core/receiver.h core/thread.h core/timespec.h filter/copy.h filter/ipsplit.h filter/layer.h filter/split.h filter/timing.h input/fpcap.h input/mmpcap.h input/pcap.h input/zero.h lib/base64url.h lib/clock.h lib/trie.h output/dnscli.h output/dnssim.h output/dnssim/internal.h output/dnssim/ll.h output/null.h output/pcap.h output/respdiff.h output/tcpcli.h output/tlscli.h output/udpcli.h
|
||||
dnsjit_SOURCES += core/channel.c core/compat.c core/file.c core/log.c core/object.c core/object/dns.c core/object/ether.c core/object/gre.c core/object/icmp6.c core/object/icmp.c core/object/ieee802.c core/object/ip6.c core/object/ip.c core/object/linuxsll.c core/object/loop.c core/object/null.c core/object/payload.c core/object/pcap.c core/object/tcp.c core/object/udp.c core/producer.c core/receiver.c core/thread.c filter/copy.c filter/ipsplit.c filter/layer.c filter/split.c filter/timing.c input/fpcap.c input/mmpcap.c input/pcap.c input/zpcap.c lib/base64url.c lib/clock.c lib/trie.c output/dnscli.c output/pcap.c output/respdiff.c output/tcpcli.c output/tlscli.c output/udpcli.c
|
||||
nobase_dnsjitinclude_HEADERS += core/assert.h core/channel.h core/compat.h core/file.h core/log.h core/object/dns.h core/object/ether.h core/object/gre.h core/object.h core/object/icmp6.h core/object/icmp.h core/object/ieee802.h core/object/ip6.h core/object/ip.h core/object/linuxsll.h core/object/loop.h core/object/null.h core/object/payload.h core/object/pcap.h core/object/tcp.h core/object/udp.h core/producer.h core/receiver.h core/thread.h core/timespec.h filter/copy.h filter/ipsplit.h filter/layer.h filter/split.h filter/timing.h input/fpcap.h input/mmpcap.h input/pcap.h input/zpcap.h lib/base64url.h lib/clock.h lib/trie.h output/dnscli.h output/pcap.h output/respdiff.h output/tcpcli.h output/tlscli.h output/udpcli.h
|
||||
|
||||
# Lua headers
|
||||
dist_dnsjit_SOURCES += core/channel.hh core/log.hh core/object/dns.hh core/object/ether.hh core/object/gre.hh core/object.hh core/object/icmp6.hh core/object/icmp.hh core/object/ieee802.hh core/object/ip6.hh core/object/ip.hh core/object/linuxsll.hh core/object/loop.hh core/object/null.hh core/object/payload.hh core/object/pcap.hh core/object/tcp.hh core/object/udp.hh core/producer.hh core/receiver.hh core/thread.hh core/timespec.hh filter/copy.hh filter/ipsplit.hh filter/layer.hh filter/split.hh filter/timing.hh input/fpcap.hh input/mmpcap.hh input/pcap.hh input/zero.hh lib/base64url.hh lib/clock.hh lib/trie.hh output/dnscli.hh output/dnssim.hh output/null.hh output/pcap.hh output/respdiff.hh output/tcpcli.hh output/tlscli.hh output/udpcli.hh
|
||||
lua_hobjects += core/channel.luaho core/log.luaho core/object/dns.luaho core/object/ether.luaho core/object/gre.luaho core/object/icmp6.luaho core/object/icmp.luaho core/object/ieee802.luaho core/object/ip6.luaho core/object/ip.luaho core/object/linuxsll.luaho core/object/loop.luaho core/object.luaho core/object/null.luaho core/object/payload.luaho core/object/pcap.luaho core/object/tcp.luaho core/object/udp.luaho core/producer.luaho core/receiver.luaho core/thread.luaho core/timespec.luaho filter/copy.luaho filter/ipsplit.luaho filter/layer.luaho filter/split.luaho filter/timing.luaho input/fpcap.luaho input/mmpcap.luaho input/pcap.luaho input/zero.luaho lib/base64url.luaho lib/clock.luaho lib/trie.luaho output/dnscli.luaho output/dnssim.luaho output/null.luaho output/pcap.luaho output/respdiff.luaho output/tcpcli.luaho output/tlscli.luaho output/udpcli.luaho
|
||||
nobase_dnsjitinclude_HEADERS += core/channel.hh core/file.hh core/log.hh core/object/dns.hh core/object/ether.hh core/object/gre.hh core/object.hh core/object/icmp6.hh core/object/icmp.hh core/object/ieee802.hh core/object/ip6.hh core/object/ip.hh core/object/linuxsll.hh core/object/loop.hh core/object/null.hh core/object/payload.hh core/object/pcap.hh core/object/tcp.hh core/object/udp.hh core/producer.hh core/receiver.hh core/thread.hh core/timespec.hh filter/copy.hh filter/ipsplit.hh filter/layer.hh filter/split.hh filter/timing.hh input/fpcap.hh input/mmpcap.hh input/pcap.hh input/zpcap.hh lib/base64url.hh lib/clock.hh lib/trie.hh output/dnscli.hh output/pcap.hh output/respdiff.hh output/tcpcli.hh output/tlscli.hh output/udpcli.hh
|
||||
lua_hobjects += core/channel.luaho core/file.luaho core/log.luaho core/object/dns.luaho core/object/ether.luaho core/object/gre.luaho core/object/icmp6.luaho core/object/icmp.luaho core/object/ieee802.luaho core/object/ip6.luaho core/object/ip.luaho core/object/linuxsll.luaho core/object/loop.luaho core/object.luaho core/object/null.luaho core/object/payload.luaho core/object/pcap.luaho core/object/tcp.luaho core/object/udp.luaho core/producer.luaho core/receiver.luaho core/thread.luaho core/timespec.luaho filter/copy.luaho filter/ipsplit.luaho filter/layer.luaho filter/split.luaho filter/timing.luaho input/fpcap.luaho input/mmpcap.luaho input/pcap.luaho input/zpcap.luaho lib/base64url.luaho lib/clock.luaho lib/trie.luaho output/dnscli.luaho output/pcap.luaho output/respdiff.luaho output/tcpcli.luaho output/tlscli.luaho output/udpcli.luaho
|
||||
|
||||
# Lua sources
|
||||
dist_dnsjit_SOURCES += core/channel.lua core/compat.lua core/log.lua core/object/dns/label.lua core/object/dns.lua core/object/dns/q.lua core/object/dns/rr.lua core/object/ether.lua core/object/gre.lua core/object/icmp6.lua core/object/icmp.lua core/object/ieee802.lua core/object/ip6.lua core/object/ip.lua core/object/linuxsll.lua core/object/loop.lua core/object.lua core/object/null.lua core/object/payload.lua core/object/pcap.lua core/objects.lua core/object/tcp.lua core/object/udp.lua core/producer.lua core/receiver.lua core/thread.lua core/timespec.lua filter/copy.lua filter/ipsplit.lua filter/layer.lua filter/split.lua filter/timing.lua input/fpcap.lua input/mmpcap.lua input/pcap.lua input/zero.lua lib/base64url.lua lib/clock.lua lib/getopt.lua lib/ip.lua lib/parseconf.lua lib/trie/iter.lua lib/trie.lua lib/trie/node.lua output/dnscli.lua output/dnssim.lua output/null.lua output/pcap.lua output/respdiff.lua output/tcpcli.lua output/tlscli.lua output/udpcli.lua
|
||||
lua_objects += core/channel.luao core/compat.luao core/log.luao core/object/dns/label.luao core/object/dns.luao core/object/dns/q.luao core/object/dns/rr.luao core/object/ether.luao core/object/gre.luao core/object/icmp6.luao core/object/icmp.luao core/object/ieee802.luao core/object/ip6.luao core/object/ip.luao core/object/linuxsll.luao core/object/loop.luao core/object.luao core/object/null.luao core/object/payload.luao core/object/pcap.luao core/objects.luao core/object/tcp.luao core/object/udp.luao core/producer.luao core/receiver.luao core/thread.luao core/timespec.luao filter/copy.luao filter/ipsplit.luao filter/layer.luao filter/split.luao filter/timing.luao input/fpcap.luao input/mmpcap.luao input/pcap.luao input/zero.luao lib/base64url.luao lib/clock.luao lib/getopt.luao lib/ip.luao lib/parseconf.luao lib/trie/iter.luao lib/trie.luao lib/trie/node.luao output/dnscli.luao output/dnssim.luao output/null.luao output/pcap.luao output/respdiff.luao output/tcpcli.luao output/tlscli.luao output/udpcli.luao
|
||||
dist_dnsjit_SOURCES += core/channel.lua core/compat.lua core/file.lua core/loader.lua core/log.lua core/object/dns/label.lua core/object/dns.lua core/object/dns/q.lua core/object/dns/rr.lua core/object/ether.lua core/object/gre.lua core/object/icmp6.lua core/object/icmp.lua core/object/ieee802.lua core/object/ip6.lua core/object/ip.lua core/object/linuxsll.lua core/object/loop.lua core/object.lua core/object/null.lua core/object/payload.lua core/object/pcap.lua core/objects.lua core/object/tcp.lua core/object/udp.lua core/producer.lua core/receiver.lua core/thread.lua core/timespec.lua filter/copy.lua filter/ipsplit.lua filter/layer.lua filter/split.lua filter/timing.lua input/fpcap.lua input/mmpcap.lua input/pcap.lua input/zero.lua input/zpcap.lua lib/base64url.lua lib/clock.lua lib/getopt.lua lib/ip.lua lib/parseconf.lua lib/trie/iter.lua lib/trie.lua lib/trie/node.lua output/dnscli.lua output/null.lua output/pcap.lua output/respdiff.lua output/tcpcli.lua output/tlscli.lua output/udpcli.lua
|
||||
lua_objects += core/channel.luao core/compat.luao core/file.luao core/loader.luao core/log.luao core/object/dns/label.luao core/object/dns.luao core/object/dns/q.luao core/object/dns/rr.luao core/object/ether.luao core/object/gre.luao core/object/icmp6.luao core/object/icmp.luao core/object/ieee802.luao core/object/ip6.luao core/object/ip.luao core/object/linuxsll.luao core/object/loop.luao core/object.luao core/object/null.luao core/object/payload.luao core/object/pcap.luao core/objects.luao core/object/tcp.luao core/object/udp.luao core/producer.luao core/receiver.luao core/thread.luao core/timespec.luao filter/copy.luao filter/ipsplit.luao filter/layer.luao filter/split.luao filter/timing.luao input/fpcap.luao input/mmpcap.luao input/pcap.luao input/zero.luao input/zpcap.luao lib/base64url.luao lib/clock.luao lib/getopt.luao lib/ip.luao lib/parseconf.luao lib/trie/iter.luao lib/trie.luao lib/trie/node.luao output/dnscli.luao output/null.luao output/pcap.luao output/respdiff.luao output/tcpcli.luao output/tlscli.luao output/udpcli.luao
|
||||
|
||||
dnsjit_LDFLAGS = -Wl,-E
|
||||
dnsjit_LDADD += $(lua_hobjects) $(lua_objects)
|
||||
|
@ -63,7 +64,7 @@ man1_MANS = dnsjit.1
|
|||
CLEANFILES += $(man1_MANS)
|
||||
|
||||
man3_MANS = dnsjit.core.3 dnsjit.lib.3 dnsjit.input.3 dnsjit.filter.3 dnsjit.output.3
|
||||
man3_MANS += dnsjit.core.channel.3 dnsjit.core.compat.3 dnsjit.core.log.3 dnsjit.core.object.3 dnsjit.core.object.dns.3 dnsjit.core.object.dns.label.3 dnsjit.core.object.dns.q.3 dnsjit.core.object.dns.rr.3 dnsjit.core.object.ether.3 dnsjit.core.object.gre.3 dnsjit.core.object.icmp.3 dnsjit.core.object.icmp6.3 dnsjit.core.object.ieee802.3 dnsjit.core.object.ip.3 dnsjit.core.object.ip6.3 dnsjit.core.object.linuxsll.3 dnsjit.core.object.loop.3 dnsjit.core.object.null.3 dnsjit.core.object.payload.3 dnsjit.core.object.pcap.3 dnsjit.core.objects.3 dnsjit.core.object.tcp.3 dnsjit.core.object.udp.3 dnsjit.core.producer.3 dnsjit.core.receiver.3 dnsjit.core.thread.3 dnsjit.core.timespec.3 dnsjit.filter.copy.3 dnsjit.filter.ipsplit.3 dnsjit.filter.layer.3 dnsjit.filter.split.3 dnsjit.filter.timing.3 dnsjit.input.fpcap.3 dnsjit.input.mmpcap.3 dnsjit.input.pcap.3 dnsjit.input.zero.3 dnsjit.lib.base64url.3 dnsjit.lib.clock.3 dnsjit.lib.getopt.3 dnsjit.lib.ip.3 dnsjit.lib.parseconf.3 dnsjit.lib.trie.3 dnsjit.lib.trie.iter.3 dnsjit.lib.trie.node.3 dnsjit.output.dnscli.3 dnsjit.output.dnssim.3 dnsjit.output.null.3 dnsjit.output.pcap.3 dnsjit.output.respdiff.3 dnsjit.output.tcpcli.3 dnsjit.output.tlscli.3 dnsjit.output.udpcli.3
|
||||
man3_MANS += dnsjit.core.channel.3 dnsjit.core.compat.3 dnsjit.core.file.3 dnsjit.core.loader.3 dnsjit.core.log.3 dnsjit.core.object.3 dnsjit.core.object.dns.3 dnsjit.core.object.dns.label.3 dnsjit.core.object.dns.q.3 dnsjit.core.object.dns.rr.3 dnsjit.core.object.ether.3 dnsjit.core.object.gre.3 dnsjit.core.object.icmp.3 dnsjit.core.object.icmp6.3 dnsjit.core.object.ieee802.3 dnsjit.core.object.ip.3 dnsjit.core.object.ip6.3 dnsjit.core.object.linuxsll.3 dnsjit.core.object.loop.3 dnsjit.core.object.null.3 dnsjit.core.object.payload.3 dnsjit.core.object.pcap.3 dnsjit.core.objects.3 dnsjit.core.object.tcp.3 dnsjit.core.object.udp.3 dnsjit.core.producer.3 dnsjit.core.receiver.3 dnsjit.core.thread.3 dnsjit.core.timespec.3 dnsjit.filter.copy.3 dnsjit.filter.ipsplit.3 dnsjit.filter.layer.3 dnsjit.filter.split.3 dnsjit.filter.timing.3 dnsjit.input.fpcap.3 dnsjit.input.mmpcap.3 dnsjit.input.pcap.3 dnsjit.input.zero.3 dnsjit.input.zpcap.3 dnsjit.lib.base64url.3 dnsjit.lib.clock.3 dnsjit.lib.getopt.3 dnsjit.lib.ip.3 dnsjit.lib.parseconf.3 dnsjit.lib.trie.3 dnsjit.lib.trie.iter.3 dnsjit.lib.trie.node.3 dnsjit.output.dnscli.3 dnsjit.output.null.3 dnsjit.output.pcap.3 dnsjit.output.respdiff.3 dnsjit.output.tcpcli.3 dnsjit.output.tlscli.3 dnsjit.output.udpcli.3
|
||||
CLEANFILES += *.3in $(man3_MANS)
|
||||
|
||||
.lua.luao:
|
||||
|
@ -129,6 +130,12 @@ dnsjit.core.channel.3in: core/channel.lua gen-manpage.lua
|
|||
dnsjit.core.compat.3in: core/compat.lua gen-manpage.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-manpage.lua" "$(srcdir)/core/compat.lua" > "$@"
|
||||
|
||||
dnsjit.core.file.3in: core/file.lua gen-manpage.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-manpage.lua" "$(srcdir)/core/file.lua" > "$@"
|
||||
|
||||
dnsjit.core.loader.3in: core/loader.lua gen-manpage.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-manpage.lua" "$(srcdir)/core/loader.lua" > "$@"
|
||||
|
||||
dnsjit.core.log.3in: core/log.lua gen-manpage.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-manpage.lua" "$(srcdir)/core/log.lua" > "$@"
|
||||
|
||||
|
@ -231,6 +238,9 @@ dnsjit.input.pcap.3in: input/pcap.lua gen-manpage.lua
|
|||
dnsjit.input.zero.3in: input/zero.lua gen-manpage.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-manpage.lua" "$(srcdir)/input/zero.lua" > "$@"
|
||||
|
||||
dnsjit.input.zpcap.3in: input/zpcap.lua gen-manpage.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-manpage.lua" "$(srcdir)/input/zpcap.lua" > "$@"
|
||||
|
||||
dnsjit.lib.base64url.3in: lib/base64url.lua gen-manpage.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-manpage.lua" "$(srcdir)/lib/base64url.lua" > "$@"
|
||||
|
||||
|
@ -258,9 +268,6 @@ dnsjit.lib.trie.node.3in: lib/trie/node.lua gen-manpage.lua
|
|||
dnsjit.output.dnscli.3in: output/dnscli.lua gen-manpage.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-manpage.lua" "$(srcdir)/output/dnscli.lua" > "$@"
|
||||
|
||||
dnsjit.output.dnssim.3in: output/dnssim.lua gen-manpage.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-manpage.lua" "$(srcdir)/output/dnssim.lua" > "$@"
|
||||
|
||||
dnsjit.output.null.3in: output/null.lua gen-manpage.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-manpage.lua" "$(srcdir)/output/null.lua" > "$@"
|
||||
|
||||
|
|
1652
src/Makefile.in
Normal file
1652
src/Makefile.in
Normal file
File diff suppressed because it is too large
Load diff
295
src/config.h.in
Normal file
295
src/config.h.in
Normal file
|
@ -0,0 +1,295 @@
|
|||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 to support Advanced Bit Manipulation */
|
||||
#undef HAVE_ABM
|
||||
|
||||
/* Define to 1 to support Multi-Precision Add-Carry Instruction Extensions */
|
||||
#undef HAVE_ADX
|
||||
|
||||
/* Define to 1 to support Advanced Encryption Standard New Instruction Set
|
||||
(AES-NI) */
|
||||
#undef HAVE_AES
|
||||
|
||||
/* Support Altivec instructions */
|
||||
#undef HAVE_ALTIVEC
|
||||
|
||||
/* Define to 1 to support Advanced Vector Extensions */
|
||||
#undef HAVE_AVX
|
||||
|
||||
/* Define to 1 to support Advanced Vector Extensions 2 */
|
||||
#undef HAVE_AVX2
|
||||
|
||||
/* Define to 1 to support AVX-512 Byte and Word Instructions */
|
||||
#undef HAVE_AVX512_BW
|
||||
|
||||
/* Define to 1 to support AVX-512 Conflict Detection Instructions */
|
||||
#undef HAVE_AVX512_CD
|
||||
|
||||
/* Define to 1 to support AVX-512 Doubleword and Quadword Instructions */
|
||||
#undef HAVE_AVX512_DQ
|
||||
|
||||
/* Define to 1 to support AVX-512 Exponential & Reciprocal Instructions */
|
||||
#undef HAVE_AVX512_ER
|
||||
|
||||
/* Define to 1 to support AVX-512 Foundation Extensions */
|
||||
#undef HAVE_AVX512_F
|
||||
|
||||
/* Define to 1 to support AVX-512 Integer Fused Multiply Add Instructions */
|
||||
#undef HAVE_AVX512_IFMA
|
||||
|
||||
/* Define to 1 to support AVX-512 Conflict Prefetch Instructions */
|
||||
#undef HAVE_AVX512_PF
|
||||
|
||||
/* Define to 1 to support AVX-512 Vector Byte Manipulation Instructions */
|
||||
#undef HAVE_AVX512_VBMI
|
||||
|
||||
/* Define to 1 to support AVX-512 Vector Length Extensions */
|
||||
#undef HAVE_AVX512_VL
|
||||
|
||||
/* Define to 1 to support Bit Manipulation Instruction Set 1 */
|
||||
#undef HAVE_BMI1
|
||||
|
||||
/* Define to 1 to support Bit Manipulation Instruction Set 2 */
|
||||
#undef HAVE_BMI2
|
||||
|
||||
/* Define to 1 if you have the <byteswap.h> header file. */
|
||||
#undef HAVE_BYTESWAP_H
|
||||
|
||||
/* Define to 1 if you have the <ck_pr.h> header file. */
|
||||
#undef HAVE_CK_PR_H
|
||||
|
||||
/* Define to 1 if you have the <ck_ring.h> header file. */
|
||||
#undef HAVE_CK_RING_H
|
||||
|
||||
/* Define to 1 if you have the `clock_nanosleep' function. */
|
||||
#undef HAVE_CLOCK_NANOSLEEP
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <endian.h> header file. */
|
||||
#undef HAVE_ENDIAN_H
|
||||
|
||||
/* Define to 1 to support Fused Multiply-Add Extensions 3 */
|
||||
#undef HAVE_FMA3
|
||||
|
||||
/* Define to 1 to support Fused Multiply-Add Extensions 4 */
|
||||
#undef HAVE_FMA4
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `ck' library (-lck). */
|
||||
#undef HAVE_LIBCK
|
||||
|
||||
/* Define to 1 if you have the `gnutls' library (-lgnutls). */
|
||||
#undef HAVE_LIBGNUTLS
|
||||
|
||||
/* Define to 1 if you have the `lmdb' library (-llmdb). */
|
||||
#undef HAVE_LIBLMDB
|
||||
|
||||
/* Define to 1 if you have the `pcap' library (-lpcap). */
|
||||
#undef HAVE_LIBPCAP
|
||||
|
||||
/* Define to 1 if you have the <lmdb.h> header file. */
|
||||
#undef HAVE_LMDB_H
|
||||
|
||||
/* Use liblz4 */
|
||||
#undef HAVE_LZ4
|
||||
|
||||
/* Define to 1 if you have the <machine/endian.h> header file. */
|
||||
#undef HAVE_MACHINE_ENDIAN_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 to support Multimedia Extensions */
|
||||
#undef HAVE_MMX
|
||||
|
||||
/* Define to 1 to support Memory Protection Extensions */
|
||||
#undef HAVE_MPX
|
||||
|
||||
/* Define to 1 if you have the `nanosleep' function. */
|
||||
#undef HAVE_NANOSLEEP
|
||||
|
||||
/* Define to 1 if you have the <net/ethernet.h> header file. */
|
||||
#undef HAVE_NET_ETHERNET_H
|
||||
|
||||
/* Define to 1 if you have the <net/ethertypes.h> header file. */
|
||||
#undef HAVE_NET_ETHERTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `pcap_activate' function. */
|
||||
#undef HAVE_PCAP_ACTIVATE
|
||||
|
||||
/* Define to 1 if you have the `pcap_create' function. */
|
||||
#undef HAVE_PCAP_CREATE
|
||||
|
||||
/* Define to 1 if the system has the type `pcap_direction_t'. */
|
||||
#undef HAVE_PCAP_DIRECTION_T
|
||||
|
||||
/* Define to 1 if you have the `pcap_open_offline_with_tstamp_precision'
|
||||
function. */
|
||||
#undef HAVE_PCAP_OPEN_OFFLINE_WITH_TSTAMP_PRECISION
|
||||
|
||||
/* Define to 1 if you have the `pcap_setdirection' function. */
|
||||
#undef HAVE_PCAP_SETDIRECTION
|
||||
|
||||
/* Define to 1 if you have the `pcap_set_immediate_mode' function. */
|
||||
#undef HAVE_PCAP_SET_IMMEDIATE_MODE
|
||||
|
||||
/* Define to 1 if you have the `pcap_set_tstamp_precision' function. */
|
||||
#undef HAVE_PCAP_SET_TSTAMP_PRECISION
|
||||
|
||||
/* Define to 1 if you have the `pcap_set_tstamp_type' function. */
|
||||
#undef HAVE_PCAP_SET_TSTAMP_TYPE
|
||||
|
||||
/* Define to 1 to support Prefetch Vector Data Into Caches WT1 */
|
||||
#undef HAVE_PREFETCHWT1
|
||||
|
||||
/* Define if you have POSIX threads libraries and header files. */
|
||||
#undef HAVE_PTHREAD
|
||||
|
||||
/* Have PTHREAD_PRIO_INHERIT. */
|
||||
#undef HAVE_PTHREAD_PRIO_INHERIT
|
||||
|
||||
/* Define to 1 to support Digital Random Number Generator */
|
||||
#undef HAVE_RDRND
|
||||
|
||||
/* Define to 1 if you have the `sched_yield' function. */
|
||||
#undef HAVE_SCHED_YIELD
|
||||
|
||||
/* Define to 1 to support Secure Hash Algorithm Extension */
|
||||
#undef HAVE_SHA
|
||||
|
||||
/* Define to 1 to support Streaming SIMD Extensions */
|
||||
#undef HAVE_SSE
|
||||
|
||||
/* Define to 1 to support Streaming SIMD Extensions */
|
||||
#undef HAVE_SSE2
|
||||
|
||||
/* Define to 1 to support Streaming SIMD Extensions 3 */
|
||||
#undef HAVE_SSE3
|
||||
|
||||
/* Define to 1 to support Streaming SIMD Extensions 4.1 */
|
||||
#undef HAVE_SSE4_1
|
||||
|
||||
/* Define to 1 to support Streaming SIMD Extensions 4.2 */
|
||||
#undef HAVE_SSE4_2
|
||||
|
||||
/* Define to 1 to support AMD Streaming SIMD Extensions 4a */
|
||||
#undef HAVE_SSE4a
|
||||
|
||||
/* Define to 1 to support Supplemental Streaming SIMD Extensions 3 */
|
||||
#undef HAVE_SSSE3
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_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/endian.h> header file. */
|
||||
#undef HAVE_SYS_ENDIAN_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 <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Support VSX instructions */
|
||||
#undef HAVE_VSX
|
||||
|
||||
/* Define to 1 to support eXtended Operations Extensions */
|
||||
#undef HAVE_XOP
|
||||
|
||||
/* Use libzstd */
|
||||
#undef HAVE_ZSTD
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the major version of this package. */
|
||||
#undef PACKAGE_MAJOR_VERSION
|
||||
|
||||
/* Define to the minor version of this package. */
|
||||
#undef PACKAGE_MINOR_VERSION
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the patch version of this package. */
|
||||
#undef PACKAGE_PATCH_VERSION
|
||||
|
||||
/* 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 necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
#undef PTHREAD_CREATE_JOINABLE
|
||||
|
||||
/* The size of `ck_ring_buffer_t', as computed by sizeof. */
|
||||
#undef SIZEOF_CK_RING_BUFFER_T
|
||||
|
||||
/* The size of `ck_ring_t', as computed by sizeof. */
|
||||
#undef SIZEOF_CK_RING_T
|
||||
|
||||
/* The size of `gnutls_certificate_credentials_t', as computed by sizeof. */
|
||||
#undef SIZEOF_GNUTLS_CERTIFICATE_CREDENTIALS_T
|
||||
|
||||
/* The size of `gnutls_session_t', as computed by sizeof. */
|
||||
#undef SIZEOF_GNUTLS_SESSION_T
|
||||
|
||||
/* The size of `pthread_cond_t', as computed by sizeof. */
|
||||
#undef SIZEOF_PTHREAD_COND_T
|
||||
|
||||
/* The size of `pthread_mutex_t', as computed by sizeof. */
|
||||
#undef SIZEOF_PTHREAD_MUTEX_T
|
||||
|
||||
/* The size of `pthread_t', as computed by sizeof. */
|
||||
#undef SIZEOF_PTHREAD_T
|
||||
|
||||
/* The size of `struct pollfd', as computed by sizeof. */
|
||||
#undef SIZEOF_STRUCT_POLLFD
|
||||
|
||||
/* The size of `struct sockaddr_storage', as computed by sizeof. */
|
||||
#undef SIZEOF_STRUCT_SOCKADDR_STORAGE
|
||||
|
||||
/* The size of `void*', as computed by sizeof. */
|
||||
#undef SIZEOF_VOIDP
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#undef TIME_WITH_SYS_TIME
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
|
@ -21,7 +21,7 @@
|
|||
#ifndef __dnsjit_core_assert_h
|
||||
#define __dnsjit_core_assert_h
|
||||
|
||||
#include "core/log.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
|
||||
#define mlassert_self() \
|
||||
if (!self) \
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
|
||||
#ifndef __dnsjit_core_channel_h
|
||||
#define __dnsjit_core_channel_h
|
||||
|
@ -36,6 +36,6 @@
|
|||
#include <ck_pr.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "core/channel.hh"
|
||||
#include <dnsjit/core/channel.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,20 +18,20 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//lua:require("dnsjit.core.log")
|
||||
//lua:require("dnsjit.core.receiver_h")
|
||||
//lua:require("dnsjit.core.producer_h")
|
||||
#include "config.h"
|
||||
|
||||
typedef struct input_zero {
|
||||
core_log_t _log;
|
||||
core_receiver_t recv;
|
||||
void* ctx;
|
||||
} input_zero_t;
|
||||
#include "core/file.h"
|
||||
|
||||
core_log_t* input_zero_log();
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void input_zero_init(input_zero_t* self);
|
||||
void input_zero_destroy(input_zero_t* self);
|
||||
void input_zero_run(input_zero_t* self, uint64_t num);
|
||||
int core_file_exists(const char* filename)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
core_producer_t input_zero_producer();
|
||||
if (stat(filename, &s)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -18,15 +18,9 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#ifndef __dnsjit_core_file_h
|
||||
#define __dnsjit_core_file_h
|
||||
|
||||
#ifndef __dnsjit_input_zero_h
|
||||
#define __dnsjit_input_zero_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "input/zero.hh"
|
||||
#include <dnsjit/core/file.hh>
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019, CZ.NIC, z.s.p.o.
|
||||
* Copyright (c) 2018-2021, OARC, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
|
@ -18,14 +18,4 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
|
||||
#ifndef __dnsjit_output_dnssim_h
|
||||
#define __dnsjit_output_dnssim_h
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "output/dnssim.hh"
|
||||
|
||||
#endif
|
||||
int core_file_exists(const char*);
|
37
src/core/file.lua
Normal file
37
src/core/file.lua
Normal file
|
@ -0,0 +1,37 @@
|
|||
-- Copyright (c) 2018-2021, OARC, Inc.
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- This file is part of dnsjit.
|
||||
--
|
||||
-- dnsjit is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- dnsjit is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-- dnsjit.core.file
|
||||
-- OS file operations
|
||||
-- require("dnsjit.core.file")
|
||||
-- local ffi = require("ffi")
|
||||
-- if ffi.C.core_file_exists("path/file") == 0 then
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- Module that exposes some file operations that are missing from Lua.
|
||||
-- .SS C functions
|
||||
-- .TP
|
||||
-- core_file_exists(path/filename)
|
||||
-- Function that takes a string and uses
|
||||
-- .B stat()
|
||||
-- to check if that path/filename exists.
|
||||
-- Returns zero if it exists.
|
||||
module(...,package.seeall)
|
||||
|
||||
require("dnsjit.core.file_h")
|
68
src/core/loader.lua
Normal file
68
src/core/loader.lua
Normal file
|
@ -0,0 +1,68 @@
|
|||
-- Copyright (c) 2018-2021, OARC, Inc.
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- This file is part of dnsjit.
|
||||
--
|
||||
-- dnsjit is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- dnsjit is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-- dnsjit.core.loader
|
||||
-- Dynamic library loader
|
||||
-- local loader = require("dnsjit.core.loader")
|
||||
-- loader.load("example-input-zero/zero")
|
||||
--
|
||||
-- Module for loading dynamic libraries (.so) in more ways then LuaJIT can.
|
||||
-- This is mainly used in external modules.
|
||||
module(...,package.seeall)
|
||||
|
||||
require("dnsjit.core.file")
|
||||
local ffi = require("ffi")
|
||||
local C = ffi.C
|
||||
|
||||
local Loader = {}
|
||||
|
||||
-- Search
|
||||
-- .B package.cpath
|
||||
-- for the given name and load the first found.
|
||||
-- If
|
||||
-- .B global
|
||||
-- is true (default true if not given) then the loaded symbols will also
|
||||
-- be available globally.
|
||||
-- Returns the loaded C library as per
|
||||
-- .BR ffi.load() .
|
||||
-- .br
|
||||
-- The
|
||||
-- .B ?
|
||||
-- in each path of
|
||||
-- .B package.cpath
|
||||
-- will be replace by the given name, so usually the ".so" part of the
|
||||
-- library does not need to be given.
|
||||
-- See
|
||||
-- .I package.cpath
|
||||
-- and
|
||||
-- .I package.loaders
|
||||
-- in Lua 5.1 for more information.
|
||||
function Loader.load(name, global)
|
||||
if global ~= false then
|
||||
global = true
|
||||
end
|
||||
for path in string.gmatch(package.cpath, "[^;]+") do
|
||||
path = path:gsub("?", name)
|
||||
if C.core_file_exists(path) == 0 then
|
||||
return ffi.load(path, global)
|
||||
end
|
||||
end
|
||||
return ffi.load(name)
|
||||
end
|
||||
|
||||
return Loader
|
|
@ -38,7 +38,7 @@
|
|||
name, 1, LOG_SETTINGS_T_INIT, &_log.settings \
|
||||
}
|
||||
|
||||
#include "core/log.hh"
|
||||
#include <dnsjit/core/log.hh>
|
||||
|
||||
#ifdef DNSJIT_NO_LOGGING
|
||||
#define ldebug(msg...)
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
#define CORE_OBJECT_DNS 50
|
||||
|
||||
#include <stdint.h>
|
||||
#include "core/object.hh"
|
||||
#include <dnsjit/core/object.hh>
|
||||
|
||||
#define CORE_OBJECT_INIT(type, prev) (core_object_t*)prev, type
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/object.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/object.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_dns_h
|
||||
#define __dnsjit_core_object_dns_h
|
||||
|
@ -27,7 +27,7 @@
|
|||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "core/object/dns.hh"
|
||||
#include <dnsjit/core/object/dns.hh>
|
||||
|
||||
#define CORE_OBJECT_DNS_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_ether_h
|
||||
#define __dnsjit_core_object_ether_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/ether.hh"
|
||||
#include <dnsjit/core/object/ether.hh>
|
||||
|
||||
#define CORE_OBJECT_ETHER_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_gre_h
|
||||
#define __dnsjit_core_object_gre_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/gre.hh"
|
||||
#include <dnsjit/core/object/gre.hh>
|
||||
|
||||
#define CORE_OBJECT_GRE_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_icmp_h
|
||||
#define __dnsjit_core_object_icmp_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/icmp.hh"
|
||||
#include <dnsjit/core/object/icmp.hh>
|
||||
|
||||
#define CORE_OBJECT_ICMP_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_icmp6_h
|
||||
#define __dnsjit_core_object_icmp6_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/icmp6.hh"
|
||||
#include <dnsjit/core/object/icmp6.hh>
|
||||
|
||||
#define CORE_OBJECT_ICMP6_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_ieee802_h
|
||||
#define __dnsjit_core_object_ieee802_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/ieee802.hh"
|
||||
#include <dnsjit/core/object/ieee802.hh>
|
||||
|
||||
#define CORE_OBJECT_IEEE802_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_ip_h
|
||||
#define __dnsjit_core_object_ip_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/ip.hh"
|
||||
#include <dnsjit/core/object/ip.hh>
|
||||
|
||||
#define CORE_OBJECT_IP_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_ip6_h
|
||||
#define __dnsjit_core_object_ip6_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/ip6.hh"
|
||||
#include <dnsjit/core/object/ip6.hh>
|
||||
|
||||
#define CORE_OBJECT_IP6_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_linuxsll_h
|
||||
#define __dnsjit_core_object_linuxsll_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/linuxsll.hh"
|
||||
#include <dnsjit/core/object/linuxsll.hh>
|
||||
|
||||
#define CORE_OBJECT_LINUXSLL_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_loop_h
|
||||
#define __dnsjit_core_object_loop_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/loop.hh"
|
||||
#include <dnsjit/core/object/loop.hh>
|
||||
|
||||
#define CORE_OBJECT_LOOP_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_null_h
|
||||
#define __dnsjit_core_object_null_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/null.hh"
|
||||
#include <dnsjit/core/object/null.hh>
|
||||
|
||||
#define CORE_OBJECT_NULL_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_payload_h
|
||||
#define __dnsjit_core_object_payload_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/payload.hh"
|
||||
#include <dnsjit/core/object/payload.hh>
|
||||
|
||||
#define CORE_OBJECT_PAYLOAD_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_pcap_h
|
||||
#define __dnsjit_core_object_pcap_h
|
||||
|
||||
#include "core/object/pcap.hh"
|
||||
#include <dnsjit/core/object/pcap.hh>
|
||||
|
||||
#define CORE_OBJECT_PCAP_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_tcp_h
|
||||
#define __dnsjit_core_object_tcp_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/tcp.hh"
|
||||
#include <dnsjit/core/object/tcp.hh>
|
||||
|
||||
#define CORE_OBJECT_TCP_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_core_object_udp_h
|
||||
#define __dnsjit_core_object_udp_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/object/udp.hh"
|
||||
#include <dnsjit/core/object/udp.hh>
|
||||
|
||||
#define CORE_OBJECT_UDP_INIT(prev) \
|
||||
{ \
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
|
||||
#ifndef __dnsjit_core_producer_h
|
||||
#define __dnsjit_core_producer_h
|
||||
|
||||
#include "core/producer.hh"
|
||||
#include <dnsjit/core/producer.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/object.h"
|
||||
#include <dnsjit/core/object.h>
|
||||
|
||||
#ifndef __dnsjit_core_receiver_h
|
||||
#define __dnsjit_core_receiver_h
|
||||
|
||||
#include "core/receiver.hh"
|
||||
#include <dnsjit/core/receiver.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
|
||||
#ifndef __dnsjit_core_thread_h
|
||||
#define __dnsjit_core_thread_h
|
||||
|
@ -26,6 +26,6 @@
|
|||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "core/thread.hh"
|
||||
#include <dnsjit/core/thread.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "core/timespec.hh"
|
||||
#include <dnsjit/core/timespec.hh>
|
||||
|
||||
#define CORE_TIMESPEC_INIT \
|
||||
{ \
|
||||
|
|
|
@ -19,14 +19,36 @@
|
|||
-- dnsjit.core.receiver
|
||||
-- Non-system depended time specification structure definition
|
||||
-- typedef struct core_timespec {
|
||||
-- uint64_t sec;
|
||||
-- uint64_t nsec;
|
||||
-- int64_t sec;
|
||||
-- int64_t nsec;
|
||||
-- } core_timespec_t;
|
||||
-- .SS C
|
||||
-- #include "core/timespec.h"
|
||||
-- .SS Lua
|
||||
-- require("dnsjit.core.timespec_h")
|
||||
-- .SS Lua functions
|
||||
-- local ts = require("dnsjit.core.timespec"):max_init()
|
||||
--
|
||||
-- Mainly used in C modules for a system independent time specification
|
||||
-- structure that can be passed to Lua.
|
||||
module(...,package.seeall)
|
||||
|
||||
require("dnsjit.core.timespec_h")
|
||||
|
||||
local ffi = require("ffi")
|
||||
|
||||
local Timespec = {}
|
||||
|
||||
-- Return a new structure with both
|
||||
-- .I sec
|
||||
-- and
|
||||
-- .I nsec
|
||||
-- set to 2LL ^ 62, the maximum positive values according to Lua.
|
||||
function Timespec:max_init()
|
||||
local ts = ffi.new("core_timespec_t")
|
||||
ts.sec = 2LL ^ 62
|
||||
ts.nsec = 2LL ^ 62
|
||||
return ts
|
||||
end
|
||||
|
||||
return Timespec
|
||||
|
|
11
src/dnsjit.c
11
src/dnsjit.c
|
@ -52,17 +52,6 @@ int main(int argc, char* argv[])
|
|||
sigset_t set;
|
||||
pthread_t sighthr;
|
||||
|
||||
#ifdef PACKAGE_NAME
|
||||
fprintf(stderr, "<< " PACKAGE_NAME
|
||||
#ifdef PACKAGE_VERSION
|
||||
" v" PACKAGE_VERSION
|
||||
#endif
|
||||
#ifdef PACKAGE_URL
|
||||
" " PACKAGE_URL
|
||||
#endif
|
||||
" >>\n");
|
||||
#endif
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: %s <file.lua> ...\n", argv[0]);
|
||||
exit(1);
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/object.h"
|
||||
#include "core/receiver.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/object.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
|
||||
#ifndef __dnsjit_filter_copy_h
|
||||
#define __dnsjit_filter_copy_h
|
||||
|
||||
#include "filter/copy.hh"
|
||||
#include <dnsjit/filter/copy.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
|
||||
#ifndef __dnsjit_filter_ipsplit_h
|
||||
#define __dnsjit_filter_ipsplit_h
|
||||
|
||||
#include "filter/ipsplit.hh"
|
||||
#include <dnsjit/filter/ipsplit.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,27 +18,27 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#include "core/object/pcap.h"
|
||||
#include "core/object/null.h"
|
||||
#include "core/object/ether.h"
|
||||
#include "core/object/loop.h"
|
||||
#include "core/object/linuxsll.h"
|
||||
#include "core/object/ieee802.h"
|
||||
#include "core/object/ip.h"
|
||||
#include "core/object/ip6.h"
|
||||
#include "core/object/gre.h"
|
||||
#include "core/object/icmp.h"
|
||||
#include "core/object/icmp6.h"
|
||||
#include "core/object/udp.h"
|
||||
#include "core/object/tcp.h"
|
||||
#include "core/object/payload.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
#include <dnsjit/core/object/pcap.h>
|
||||
#include <dnsjit/core/object/null.h>
|
||||
#include <dnsjit/core/object/ether.h>
|
||||
#include <dnsjit/core/object/loop.h>
|
||||
#include <dnsjit/core/object/linuxsll.h>
|
||||
#include <dnsjit/core/object/ieee802.h>
|
||||
#include <dnsjit/core/object/ip.h>
|
||||
#include <dnsjit/core/object/ip6.h>
|
||||
#include <dnsjit/core/object/gre.h>
|
||||
#include <dnsjit/core/object/icmp.h>
|
||||
#include <dnsjit/core/object/icmp6.h>
|
||||
#include <dnsjit/core/object/udp.h>
|
||||
#include <dnsjit/core/object/tcp.h>
|
||||
#include <dnsjit/core/object/payload.h>
|
||||
|
||||
#ifndef __dnsjit_filter_layer_h
|
||||
#define __dnsjit_filter_layer_h
|
||||
|
||||
#include "filter/layer.hh"
|
||||
#include <dnsjit/filter/layer.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
|
||||
#ifndef __dnsjit_filter_split_h
|
||||
#define __dnsjit_filter_split_h
|
||||
|
||||
#include "filter/split.hh"
|
||||
#include <dnsjit/filter/split.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
|
||||
#ifndef __dnsjit_filter_timing_h
|
||||
#define __dnsjit_filter_timing_h
|
||||
|
||||
#include "filter/timing.hh"
|
||||
#include <dnsjit/filter/timing.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,130 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo '# Copyright (c) 2018-2021, OARC, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of dnsjit.
|
||||
#
|
||||
# dnsjit is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# dnsjit is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
CLEANFILES = *.gcda *.gcno *.gcov
|
||||
|
||||
SUBDIRS = test
|
||||
|
||||
AM_CFLAGS = -Werror=attributes \
|
||||
-I$(srcdir) \
|
||||
-I$(top_srcdir) \
|
||||
$(SIMD_FLAGS) $(CPUEXT_FLAGS) \
|
||||
$(PTHREAD_CFLAGS) \
|
||||
$(luajit_CFLAGS) \
|
||||
$(libuv_CFLAGS) \
|
||||
$(libnghttp2_CFLAGS)
|
||||
|
||||
EXTRA_DIST = gen-manpage.lua gen-compat.lua gen-errno.sh dnsjit.1in
|
||||
|
||||
BUILT_SOURCES = core/compat.hh core/log_errstr.c
|
||||
|
||||
bin_PROGRAMS = dnsjit
|
||||
|
||||
dnsjit_SOURCES = dnsjit.c globals.c
|
||||
dist_dnsjit_SOURCES = core.lua lib.lua input.lua filter.lua globals.h \
|
||||
output.lua
|
||||
lua_hobjects = core/compat.luaho
|
||||
lua_objects = core.luao lib.luao input.luao filter.luao output.luao
|
||||
dnsjit_LDADD = $(PTHREAD_LIBS) $(luajit_LIBS) $(libuv_LIBS) $(libnghttp2_LIBS)
|
||||
|
||||
# C source and headers';
|
||||
|
||||
echo "dnsjit_SOURCES +=`find core lib input filter output -type f -name '*.c' | sort | while read line; do echo -n " $line"; done`"
|
||||
echo "dist_dnsjit_SOURCES +=`find core lib input filter output -type f -name '*.h' | sort | while read line; do echo -n " $line"; done`"
|
||||
|
||||
echo '
|
||||
# Lua headers'
|
||||
echo "dist_dnsjit_SOURCES +=`find core lib input filter output -type f -name '*.hh' | sort | while read line; do echo -n " $line"; done`"
|
||||
echo "lua_hobjects +=`find core lib input filter output -type f -name '*.hh' | sed -e 's%.hh%.luaho%g' | sort | while read line; do echo -n " $line"; done`"
|
||||
|
||||
echo '
|
||||
# Lua sources'
|
||||
echo "dist_dnsjit_SOURCES +=`find core lib input filter output -type f -name '*.lua' | sort | while read line; do echo -n " $line"; done`"
|
||||
echo "lua_objects +=`find core lib input filter output -type f -name '*.lua' | sed -e 's%.lua%.luao%g' | sort | while read line; do echo -n " $line"; done`"
|
||||
|
||||
echo '
|
||||
dnsjit_LDFLAGS = -Wl,-E
|
||||
dnsjit_LDADD += $(lua_hobjects) $(lua_objects)
|
||||
CLEANFILES += $(lua_hobjects) $(lua_objects)
|
||||
|
||||
man1_MANS = dnsjit.1
|
||||
CLEANFILES += $(man1_MANS)
|
||||
|
||||
man3_MANS = dnsjit.core.3 dnsjit.lib.3 dnsjit.input.3 dnsjit.filter.3 dnsjit.output.3';
|
||||
echo "man3_MANS +=`find core lib input filter output -type f -name '*.lua' | sed -e 's%.lua%.3%g' | sed -e 's%/%.%g' | sort | while read line; do echo -n " dnsjit.$line"; done`"
|
||||
|
||||
echo 'CLEANFILES += *.3in $(man3_MANS)
|
||||
|
||||
.lua.luao:
|
||||
@mkdir -p `dirname "$@"`
|
||||
$(LUAJIT) -bg -n "dnsjit.`echo \"$@\" | sed '"'"'s%\..*%%'"'"' | sed '"'"'s%/%.%g'"'"'`" -t o "$<" "$@"
|
||||
|
||||
.luah.luaho:
|
||||
@mkdir -p `dirname "$@"`
|
||||
$(LUAJIT) -bg -n "dnsjit.`echo \"$@\" | sed '"'"'s%\..*%%'"'"' | sed '"'"'s%/%.%g'"'"'`_h" -t o "$<" "$@"
|
||||
|
||||
.hh.luah:
|
||||
@mkdir -p `dirname "$@"`
|
||||
@echo '"'"'module(...,package.seeall);'"'"' > "$@"
|
||||
@cat "$<" | grep '"'"'^//lua:'"'"' | sed '"'"'s%^//lua:%%'"'"' >> "$@"
|
||||
@echo '"'"'require("ffi").cdef[['"'"' >> "$@"
|
||||
@cat "$<" | grep -v '"'"'^#'"'"' >> "$@"
|
||||
@echo '"'"']]'"'"' >> "$@"
|
||||
|
||||
.1in.1:
|
||||
sed -e '"'"'s,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g'"'"' \
|
||||
-e '"'"'s,[@]PACKAGE_URL[@],$(PACKAGE_URL),g'"'"' \
|
||||
-e '"'"'s,[@]PACKAGE_BUGREPORT[@],$(PACKAGE_BUGREPORT),g'"'"' \
|
||||
< "$<" > "$@"
|
||||
|
||||
.3in.3:
|
||||
sed -e '"'"'s,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g'"'"' \
|
||||
-e '"'"'s,[@]PACKAGE_URL[@],$(PACKAGE_URL),g'"'"' \
|
||||
-e '"'"'s,[@]PACKAGE_BUGREPORT[@],$(PACKAGE_BUGREPORT),g'"'"' \
|
||||
< "$<" > "$@"
|
||||
|
||||
if ENABLE_GCOV
|
||||
gcov-local:
|
||||
for src in $(dnsjit_SOURCES); do \
|
||||
gcov -x -l -r -s "$(srcdir)" "$$src"; \
|
||||
done
|
||||
endif
|
||||
|
||||
core/compat.hh: gen-compat.lua
|
||||
$(LUAJIT) "$(srcdir)/gen-compat.lua" > "$@"
|
||||
|
||||
core/log_errstr.c: gen-errno.sh
|
||||
"$(srcdir)/gen-errno.sh" > "$@"
|
||||
';
|
||||
|
||||
for file in core.lua lib.lua input.lua filter.lua output.lua; do
|
||||
man=`echo "$file"|sed -e 's%.lua%.3%g'|sed -e 's%/%.%g'`
|
||||
echo "
|
||||
dnsjit.${man}in: $file gen-manpage.lua
|
||||
\$(LUAJIT) \"\$(srcdir)/gen-manpage.lua\" \"\$(srcdir)/$file\" > \"\$@\"";
|
||||
done
|
||||
|
||||
find core lib input filter output -type f -name '*.lua' | sort | while read file; do
|
||||
man=`echo "$file"|sed -e 's%.lua%.3%g'|sed -e 's%/%.%g'`
|
||||
echo "
|
||||
dnsjit.${man}in: $file gen-manpage.lua
|
||||
\$(LUAJIT) \"\$(srcdir)/gen-manpage.lua\" \"\$(srcdir)/$file\" > \"\$@\"";
|
||||
done
|
|
@ -100,9 +100,10 @@ for line in io.lines(arg[1]) do
|
|||
end
|
||||
|
||||
print[[
|
||||
.SH AUTHORS
|
||||
.SH AUTHORS and CONTRIBUTORS
|
||||
Jerry Lundström (DNS-OARC),
|
||||
Tomáš Křížek (CZ.NIC)
|
||||
Tomáš Křížek (CZ.NIC),
|
||||
Petr Špaček (ISC)
|
||||
.LP
|
||||
Maintained by DNS-OARC
|
||||
.LP
|
||||
|
|
|
@ -25,5 +25,6 @@ module(...,package.seeall)
|
|||
-- dnsjit.input.fpcap (3),
|
||||
-- dnsjit.input.mmpcap (3),
|
||||
-- dnsjit.input.pcap (3),
|
||||
-- dnsjit.input.zero (3)
|
||||
-- dnsjit.input.zero (3),
|
||||
-- dnsjit.input.zpcap (3)
|
||||
return
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "core/assert.h"
|
||||
#include "core/object/pcap.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
#include <endian.h>
|
||||
|
@ -60,7 +61,7 @@ static input_fpcap_t _defaults = {
|
|||
0, 0,
|
||||
0, 0, 0,
|
||||
CORE_OBJECT_PCAP_INIT(0),
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0
|
||||
};
|
||||
|
@ -91,6 +92,16 @@ static int _open(input_fpcap_t* self)
|
|||
{
|
||||
mlassert_self();
|
||||
|
||||
#if _POSIX_C_SOURCE >= 200112L || defined(__FreeBSD__)
|
||||
if (self->use_fadvise) {
|
||||
int err = posix_fadvise(fileno((FILE*)self->file), 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
if (err) {
|
||||
lcritical("posix_fadvise() failed: %s", core_log_errstr(err));
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fread(&self->magic_number, 1, 4, self->file) != 4
|
||||
|| fread(&self->version_major, 1, 2, self->file) != 2
|
||||
|| fread(&self->version_minor, 1, 2, self->file) != 2
|
||||
|
|
|
@ -18,14 +18,14 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#include "core/object/pcap.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
#include <dnsjit/core/object/pcap.h>
|
||||
|
||||
#ifndef __dnsjit_input_fpcap_h
|
||||
#define __dnsjit_input_fpcap_h
|
||||
|
||||
#include "input/fpcap.hh"
|
||||
#include <dnsjit/input/fpcap.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef struct input_fpcap {
|
|||
core_object_pcap_t prod_pkt;
|
||||
|
||||
void* file;
|
||||
int extern_file;
|
||||
int extern_file, use_fadvise;
|
||||
size_t pkts;
|
||||
uint8_t* buf;
|
||||
size_t buf_size;
|
||||
|
|
|
@ -100,6 +100,15 @@ function Fpcap:produce()
|
|||
return C.input_fpcap_producer(self.obj), self.obj
|
||||
end
|
||||
|
||||
-- Use
|
||||
-- .B posix_fadvise()
|
||||
-- to indicate sequential reading (if supported), may increase performance.
|
||||
-- MUST be called before
|
||||
-- .BR open() .
|
||||
function Fpcap:fadvise_sequential()
|
||||
self.obj.use_fadvise = 1
|
||||
end
|
||||
|
||||
-- Open a PCAP file for processing and read the PCAP header.
|
||||
-- Returns 0 on success.
|
||||
function Fpcap:open(file)
|
||||
|
|
|
@ -18,14 +18,14 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#include "core/object/pcap.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
#include <dnsjit/core/object/pcap.h>
|
||||
|
||||
#ifndef __dnsjit_input_mmpcap_h
|
||||
#define __dnsjit_input_mmpcap_h
|
||||
|
||||
#include "input/mmpcap.hh"
|
||||
#include <dnsjit/input/mmpcap.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,16 +18,16 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#include "core/object/pcap.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
#include <dnsjit/core/object/pcap.h>
|
||||
|
||||
#ifndef __dnsjit_input_pcap_h
|
||||
#define __dnsjit_input_pcap_h
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
#include "input/pcap.hh"
|
||||
#include <dnsjit/input/pcap.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, OARC, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "input/zero.h"
|
||||
#include "core/assert.h"
|
||||
#include "core/object/null.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
static core_log_t _log = LOG_T_INIT("input.zero");
|
||||
static input_zero_t _defaults = {
|
||||
LOG_T_INIT_OBJ("input.zero"),
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
static core_object_null_t _null = CORE_OBJECT_NULL_INIT(0);
|
||||
|
||||
core_log_t* input_zero_log()
|
||||
{
|
||||
return &_log;
|
||||
}
|
||||
|
||||
void input_zero_init(input_zero_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
*self = _defaults;
|
||||
}
|
||||
|
||||
void input_zero_destroy(input_zero_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
}
|
||||
|
||||
void input_zero_run(input_zero_t* self, uint64_t num)
|
||||
{
|
||||
mlassert_self();
|
||||
if (!self->recv) {
|
||||
lfatal("no receiver set");
|
||||
}
|
||||
|
||||
while (num--) {
|
||||
self->recv(self->ctx, (core_object_t*)&_null);
|
||||
}
|
||||
}
|
||||
|
||||
static const core_object_t* _produce(void* ctx)
|
||||
{
|
||||
return (core_object_t*)&_null;
|
||||
}
|
||||
|
||||
core_producer_t input_zero_producer()
|
||||
{
|
||||
return _produce;
|
||||
}
|
|
@ -17,59 +17,15 @@
|
|||
-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-- dnsjit.input.zero
|
||||
-- Generate empty objects (/dev/zero)
|
||||
-- local input = require("dnsjit.input.zero").new()
|
||||
-- input:receiver(filter_or_output)
|
||||
-- input:run(1e6)
|
||||
-- Dummy layer to example.input.zero
|
||||
--
|
||||
-- Input module for generating empty
|
||||
-- .I core.object.null
|
||||
-- objects, mostly used for testing.
|
||||
-- This module has moved to example.input.zero, see examples/modules/input-example in
|
||||
-- dnsjit source repository.
|
||||
module(...,package.seeall)
|
||||
|
||||
require("dnsjit.input.zero_h")
|
||||
local ffi = require("ffi")
|
||||
local C = ffi.C
|
||||
|
||||
local t_name = "input_zero_t"
|
||||
local input_zero_t = ffi.typeof(t_name)
|
||||
local Zero = {}
|
||||
|
||||
-- Create a new Zero input.
|
||||
function Zero.new()
|
||||
local self = {
|
||||
_receiver = nil,
|
||||
obj = input_zero_t(),
|
||||
}
|
||||
C.input_zero_init(self.obj)
|
||||
ffi.gc(self.obj, C.input_zero_destroy)
|
||||
return setmetatable(self, { __index = Zero })
|
||||
ok, cls = pcall(require, "example.input.zero")
|
||||
if not ok then
|
||||
error("You need to install the example module input-example\n" .. cls)
|
||||
end
|
||||
|
||||
-- Return the Log object to control logging of this instance or module.
|
||||
function Zero:log()
|
||||
if self == nil then
|
||||
return C.input_zero_log()
|
||||
end
|
||||
return self.obj._log
|
||||
end
|
||||
|
||||
-- Set the receiver to pass objects to.
|
||||
function Zero:receiver(o)
|
||||
self.obj.recv, self.obj.ctx = o:receive()
|
||||
self._receiver = o
|
||||
end
|
||||
|
||||
-- Return the C functions and context for producing objects.
|
||||
function Zero:produce()
|
||||
return C.input_zero_producer(), self.obj
|
||||
end
|
||||
|
||||
-- Generate
|
||||
-- .I num
|
||||
-- empty objects and send them to the receiver.
|
||||
function Zero:run(num)
|
||||
C.input_zero_run(self.obj, num)
|
||||
end
|
||||
|
||||
return Zero
|
||||
return cls
|
||||
|
|
582
src/input/zpcap.c
Normal file
582
src/input/zpcap.c
Normal file
|
@ -0,0 +1,582 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, OARC, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "input/zpcap.h"
|
||||
#include "core/assert.h"
|
||||
#include "core/object/pcap.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
#include <endian.h>
|
||||
#else
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
#include <sys/endian.h>
|
||||
#else
|
||||
#ifdef HAVE_MACHINE_ENDIAN_H
|
||||
#include <machine/endian.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_BYTESWAP_H
|
||||
#include <byteswap.h>
|
||||
#endif
|
||||
#ifndef bswap_16
|
||||
#ifndef bswap16
|
||||
#define bswap_16(x) swap16(x)
|
||||
#define bswap_32(x) swap32(x)
|
||||
#define bswap_64(x) swap64(x)
|
||||
#else
|
||||
#define bswap_16(x) bswap16(x)
|
||||
#define bswap_32(x) bswap32(x)
|
||||
#define bswap_64(x) bswap64(x)
|
||||
#endif
|
||||
#endif
|
||||
#include <pcap/pcap.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_LZ4
|
||||
#include <lz4frame.h>
|
||||
struct _lz4_ctx {
|
||||
LZ4F_dctx* ctx;
|
||||
LZ4F_decompressOptions_t opts;
|
||||
};
|
||||
#define lz4 ((struct _lz4_ctx*)self->comp_ctx)
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD
|
||||
#include <zstd.h>
|
||||
struct _zstd_ctx {
|
||||
ZSTD_DCtx* ctx;
|
||||
ZSTD_inBuffer in;
|
||||
ZSTD_outBuffer out;
|
||||
};
|
||||
#define zstd ((struct _zstd_ctx*)self->comp_ctx)
|
||||
#endif
|
||||
|
||||
#define MAX_SNAPLEN 0x40000
|
||||
|
||||
static core_log_t _log = LOG_T_INIT("input.zpcap");
|
||||
static input_zpcap_t _defaults = {
|
||||
LOG_T_INIT_OBJ("input.zpcap"),
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
CORE_OBJECT_PCAP_INIT(0),
|
||||
input_zpcap_type_none, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0
|
||||
};
|
||||
|
||||
core_log_t* input_zpcap_log()
|
||||
{
|
||||
return &_log;
|
||||
}
|
||||
|
||||
void input_zpcap_init(input_zpcap_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
*self = _defaults;
|
||||
}
|
||||
|
||||
void input_zpcap_destroy(input_zpcap_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
switch (self->compression) {
|
||||
#ifdef HAVE_LZ4
|
||||
case input_zpcap_type_lz4: {
|
||||
LZ4F_errorCode_t code;
|
||||
|
||||
if (lz4) {
|
||||
if (lz4->ctx && (code = LZ4F_freeDecompressionContext(lz4->ctx))) {
|
||||
lfatal("LZ4F_freeDecompressionContext() failed: %s", LZ4F_getErrorName(code));
|
||||
}
|
||||
}
|
||||
free(lz4);
|
||||
free(self->in);
|
||||
free(self->out);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD
|
||||
case input_zpcap_type_zstd:
|
||||
if (zstd) {
|
||||
if (zstd->ctx) {
|
||||
ZSTD_freeDCtx(zstd->ctx);
|
||||
}
|
||||
}
|
||||
free(zstd);
|
||||
free(self->in);
|
||||
free(self->out);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!self->extern_file && self->file) {
|
||||
fclose(self->file);
|
||||
}
|
||||
free(self->buf);
|
||||
}
|
||||
|
||||
static ssize_t _read(input_zpcap_t* self, void* dst, size_t len, void** dstp)
|
||||
{
|
||||
switch (self->compression) {
|
||||
#ifdef HAVE_LZ4
|
||||
case input_zpcap_type_lz4: {
|
||||
size_t need = len;
|
||||
|
||||
if (dstp && self->out_have > need) {
|
||||
*dstp = self->out + self->out_at;
|
||||
self->out_have -= need;
|
||||
self->out_at += need;
|
||||
return len;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (self->out_have > need) {
|
||||
memcpy(dst, self->out + self->out_at, need);
|
||||
self->out_have -= need;
|
||||
self->out_at += need;
|
||||
return len;
|
||||
}
|
||||
|
||||
memcpy(dst, self->out + self->out_at, self->out_have);
|
||||
need -= self->out_have;
|
||||
dst += self->out_have;
|
||||
|
||||
ssize_t n = fread(self->in + self->in_at, 1, self->in_size - self->in_have, self->file);
|
||||
if (n < 0) {
|
||||
return n;
|
||||
}
|
||||
self->in_at += n;
|
||||
self->in_have += n;
|
||||
if (!self->in_have) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t dst_size = self->out_size, src_size = self->in_have;
|
||||
size_t code = LZ4F_decompress(lz4->ctx, self->out, &dst_size, self->in, &src_size, &lz4->opts);
|
||||
if (LZ4F_isError(code)) {
|
||||
lfatal("LZ4F_decompress() failed: %s", LZ4F_getErrorName(code));
|
||||
}
|
||||
|
||||
if (src_size < self->in_have) {
|
||||
self->in_have -= src_size;
|
||||
memmove(self->in, self->in + src_size, self->in_have);
|
||||
self->in_at = self->in_have;
|
||||
} else {
|
||||
self->in_at = 0;
|
||||
self->in_have = 0;
|
||||
}
|
||||
|
||||
self->out_at = 0;
|
||||
self->out_have = dst_size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD
|
||||
case input_zpcap_type_zstd: {
|
||||
size_t need = len;
|
||||
|
||||
if (dstp && self->out_have > need) {
|
||||
*dstp = self->out + self->out_at;
|
||||
self->out_have -= need;
|
||||
self->out_at += need;
|
||||
return len;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (self->out_have > need) {
|
||||
memcpy(dst, self->out + self->out_at, need);
|
||||
self->out_have -= need;
|
||||
self->out_at += need;
|
||||
return len;
|
||||
}
|
||||
|
||||
memcpy(dst, self->out + self->out_at, self->out_have);
|
||||
need -= self->out_have;
|
||||
dst += self->out_have;
|
||||
|
||||
if (zstd->in.pos >= zstd->in.size) {
|
||||
ssize_t n = fread(self->in, 1, self->in_size, self->file);
|
||||
if (n < 1) {
|
||||
return n;
|
||||
}
|
||||
zstd->in.size = n;
|
||||
zstd->in.pos = 0;
|
||||
}
|
||||
|
||||
zstd->out.size = self->out_size;
|
||||
zstd->out.pos = 0;
|
||||
size_t code = ZSTD_decompressStream(zstd->ctx, &zstd->out, &zstd->in);
|
||||
if (ZSTD_isError(code)) {
|
||||
lfatal("ZSTD_decompressStream() failed: %s", ZSTD_getErrorName(code));
|
||||
}
|
||||
|
||||
self->out_have = zstd->out.pos;
|
||||
self->out_at = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int _open(input_zpcap_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
#if _POSIX_C_SOURCE >= 200112L || defined(__FreeBSD__)
|
||||
if (self->use_fadvise) {
|
||||
int err = posix_fadvise(fileno((FILE*)self->file), 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
if (err) {
|
||||
lcritical("posix_fadvise() failed: %s", core_log_errstr(err));
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (self->compression) {
|
||||
#ifdef HAVE_LZ4
|
||||
case input_zpcap_type_lz4: {
|
||||
LZ4F_errorCode_t code;
|
||||
|
||||
if (lz4) {
|
||||
if (lz4->ctx && (code = LZ4F_freeDecompressionContext(lz4->ctx))) {
|
||||
lfatal("LZ4F_freeDecompressionContext() failed: %s", LZ4F_getErrorName(code));
|
||||
}
|
||||
}
|
||||
free(lz4);
|
||||
free(self->in);
|
||||
free(self->out);
|
||||
|
||||
lfatal_oom(self->comp_ctx = calloc(1, sizeof(struct _lz4_ctx)));
|
||||
if ((code = LZ4F_createDecompressionContext(&lz4->ctx, LZ4F_VERSION))) {
|
||||
lfatal("LZ4F_createDecompressionContext() failed: %s", LZ4F_getErrorName(code));
|
||||
}
|
||||
lz4->opts.stableDst = 1;
|
||||
|
||||
self->in_size = 256 * 1024;
|
||||
lfatal_oom(self->in = malloc(self->in_size));
|
||||
self->out_size = 256 * 1024;
|
||||
lfatal_oom(self->out = malloc(self->out_size));
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD
|
||||
case input_zpcap_type_zstd:
|
||||
if (zstd) {
|
||||
if (zstd->ctx) {
|
||||
ZSTD_freeDCtx(zstd->ctx);
|
||||
}
|
||||
}
|
||||
free(zstd);
|
||||
free(self->in);
|
||||
free(self->out);
|
||||
|
||||
lfatal_oom(self->comp_ctx = calloc(1, sizeof(struct _zstd_ctx)));
|
||||
lfatal_oom(zstd->ctx = ZSTD_createDCtx());
|
||||
self->in_size = ZSTD_DStreamInSize();
|
||||
lfatal_oom(self->in = malloc(self->in_size));
|
||||
self->out_size = ZSTD_DStreamOutSize();
|
||||
lfatal_oom(self->out = malloc(self->out_size));
|
||||
|
||||
zstd->in.src = self->in;
|
||||
zstd->out.dst = self->out;
|
||||
zstd->out.size = self->out_size;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
lcritical("no support for selected compression");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (_read(self, &self->magic_number, 4, 0) != 4
|
||||
|| _read(self, &self->version_major, 2, 0) != 2
|
||||
|| _read(self, &self->version_minor, 2, 0) != 2
|
||||
|| _read(self, &self->thiszone, 4, 0) != 4
|
||||
|| _read(self, &self->sigfigs, 4, 0) != 4
|
||||
|| _read(self, &self->snaplen, 4, 0) != 4
|
||||
|| _read(self, &self->network, 4, 0) != 4) {
|
||||
lcritical("could not read full PCAP header");
|
||||
return -2;
|
||||
}
|
||||
switch (self->magic_number) {
|
||||
case 0x4d3cb2a1:
|
||||
self->is_nanosec = 1;
|
||||
case 0xd4c3b2a1:
|
||||
self->is_swapped = 1;
|
||||
self->version_major = bswap_16(self->version_major);
|
||||
self->version_minor = bswap_16(self->version_minor);
|
||||
self->thiszone = (int32_t)bswap_32((uint32_t)self->thiszone);
|
||||
self->sigfigs = bswap_32(self->sigfigs);
|
||||
self->snaplen = bswap_32(self->snaplen);
|
||||
self->network = bswap_32(self->network);
|
||||
break;
|
||||
case 0xa1b2c3d4:
|
||||
case 0xa1b23c4d:
|
||||
break;
|
||||
default:
|
||||
lcritical("invalid PCAP header");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (self->snaplen > MAX_SNAPLEN) {
|
||||
lcritical("too large snaplen (%u)", self->snaplen);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (self->version_major != 2 || self->version_minor != 4) {
|
||||
lcritical("unsupported PCAP version v%u.%u", self->version_major, self->version_minor);
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translation taken from https://github.com/the-tcpdump-group/libpcap/blob/90543970fd5fbed261d3637f5ec4811d7dde4e49/pcap-common.c#L1212 .
|
||||
*/
|
||||
switch (self->network) {
|
||||
case 101:
|
||||
self->linktype = DLT_RAW;
|
||||
break;
|
||||
#ifdef DLT_FR
|
||||
case 107: /* LINKTYPE_FRELAY */
|
||||
self->linktype = DLT_FR;
|
||||
break;
|
||||
#endif
|
||||
case 100: /* LINKTYPE_ATM_RFC1483 */
|
||||
self->linktype = DLT_ATM_RFC1483;
|
||||
break;
|
||||
case 102: /* LINKTYPE_SLIP_BSDOS */
|
||||
self->linktype = DLT_SLIP_BSDOS;
|
||||
break;
|
||||
case 103: /* LINKTYPE_PPP_BSDOS */
|
||||
self->linktype = DLT_PPP_BSDOS;
|
||||
break;
|
||||
case 104: /* LINKTYPE_C_HDLC */
|
||||
self->linktype = DLT_C_HDLC;
|
||||
break;
|
||||
case 106: /* LINKTYPE_ATM_CLIP */
|
||||
self->linktype = DLT_ATM_CLIP;
|
||||
break;
|
||||
case 50: /* LINKTYPE_PPP_HDLC */
|
||||
self->linktype = DLT_PPP_SERIAL;
|
||||
break;
|
||||
case 51: /* LINKTYPE_PPP_ETHER */
|
||||
self->linktype = DLT_PPP_ETHER;
|
||||
break;
|
||||
default:
|
||||
self->linktype = self->network;
|
||||
}
|
||||
|
||||
lfatal_oom(self->buf = malloc(self->snaplen));
|
||||
self->prod_pkt.snaplen = self->snaplen;
|
||||
self->prod_pkt.linktype = self->linktype;
|
||||
self->prod_pkt.is_swapped = self->is_swapped;
|
||||
|
||||
ldebug("pcap v%u.%u snaplen:%lu %s", self->version_major, self->version_minor, self->snaplen, self->is_swapped ? " swapped" : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int input_zpcap_open(input_zpcap_t* self, const char* file)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(file, "file is nil");
|
||||
|
||||
if (self->file) {
|
||||
lfatal("already opened");
|
||||
}
|
||||
|
||||
if (!(self->file = fopen(file, "rb"))) {
|
||||
lcritical("fopen(%s) error: %s", file, core_log_errstr(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _open(self);
|
||||
}
|
||||
|
||||
int input_zpcap_openfp(input_zpcap_t* self, void* fp)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
if (self->file) {
|
||||
lfatal("already opened");
|
||||
}
|
||||
|
||||
self->file = fp;
|
||||
self->extern_file = 1;
|
||||
|
||||
return _open(self);
|
||||
}
|
||||
|
||||
int input_zpcap_run(input_zpcap_t* self)
|
||||
{
|
||||
struct {
|
||||
uint32_t ts_sec;
|
||||
uint32_t ts_usec;
|
||||
uint32_t incl_len;
|
||||
uint32_t orig_len;
|
||||
} hdr;
|
||||
core_object_pcap_t pkt = CORE_OBJECT_PCAP_INIT(0);
|
||||
int ret;
|
||||
mlassert_self();
|
||||
|
||||
if (!self->file) {
|
||||
lfatal("no PCAP opened");
|
||||
}
|
||||
if (!self->recv) {
|
||||
lfatal("no receiver set");
|
||||
}
|
||||
|
||||
pkt.snaplen = self->snaplen;
|
||||
pkt.linktype = self->linktype;
|
||||
pkt.is_swapped = self->is_swapped;
|
||||
|
||||
while ((ret = _read(self, &hdr, 16, 0)) == 16) {
|
||||
if (self->is_swapped) {
|
||||
hdr.ts_sec = bswap_32(hdr.ts_sec);
|
||||
hdr.ts_usec = bswap_32(hdr.ts_usec);
|
||||
hdr.incl_len = bswap_32(hdr.incl_len);
|
||||
hdr.orig_len = bswap_32(hdr.orig_len);
|
||||
}
|
||||
if (hdr.incl_len > self->snaplen) {
|
||||
lwarning("invalid packet length, larger then snaplen");
|
||||
return -1;
|
||||
}
|
||||
pkt.bytes = (unsigned char*)self->buf;
|
||||
if (_read(self, self->buf, hdr.incl_len, (void**)&pkt.bytes) != hdr.incl_len) {
|
||||
lwarning("could not read all of packet, aborting");
|
||||
return -1;
|
||||
}
|
||||
|
||||
self->pkts++;
|
||||
|
||||
pkt.ts.sec = hdr.ts_sec;
|
||||
if (self->is_nanosec) {
|
||||
pkt.ts.nsec = hdr.ts_usec;
|
||||
} else {
|
||||
pkt.ts.nsec = hdr.ts_usec * 1000;
|
||||
}
|
||||
pkt.caplen = hdr.incl_len;
|
||||
pkt.len = hdr.orig_len;
|
||||
|
||||
self->recv(self->ctx, (core_object_t*)&pkt);
|
||||
}
|
||||
if (ret) {
|
||||
lwarning("could not read next PCAP header, aborting");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int input_zpcap_have_support(input_zpcap_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
switch (self->compression) {
|
||||
#ifdef HAVE_LZ4
|
||||
case input_zpcap_type_lz4:
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD
|
||||
case input_zpcap_type_zstd:
|
||||
return 1;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const core_object_t* _produce(input_zpcap_t* self)
|
||||
{
|
||||
struct {
|
||||
uint32_t ts_sec;
|
||||
uint32_t ts_usec;
|
||||
uint32_t incl_len;
|
||||
uint32_t orig_len;
|
||||
} hdr;
|
||||
int ret;
|
||||
mlassert_self();
|
||||
|
||||
if (self->is_broken) {
|
||||
lwarning("PCAP is broken, will not read next packet");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ret = _read(self, &hdr, 16, 0)) != 16) {
|
||||
if (ret) {
|
||||
lwarning("could not read next PCAP header, aborting");
|
||||
self->is_broken = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->is_swapped) {
|
||||
hdr.ts_sec = bswap_32(hdr.ts_sec);
|
||||
hdr.ts_usec = bswap_32(hdr.ts_usec);
|
||||
hdr.incl_len = bswap_32(hdr.incl_len);
|
||||
hdr.orig_len = bswap_32(hdr.orig_len);
|
||||
}
|
||||
if (hdr.incl_len > self->snaplen) {
|
||||
lwarning("invalid packet length, larger then snaplen");
|
||||
self->is_broken = 1;
|
||||
return 0;
|
||||
}
|
||||
self->prod_pkt.bytes = (unsigned char*)self->buf;
|
||||
if (_read(self, self->buf, hdr.incl_len, (void**)&self->prod_pkt.bytes) != hdr.incl_len) {
|
||||
lwarning("could not read all of packet, aborting");
|
||||
self->is_broken = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
self->pkts++;
|
||||
|
||||
self->prod_pkt.ts.sec = hdr.ts_sec;
|
||||
if (self->is_nanosec) {
|
||||
self->prod_pkt.ts.nsec = hdr.ts_usec;
|
||||
} else {
|
||||
self->prod_pkt.ts.nsec = hdr.ts_usec * 1000;
|
||||
}
|
||||
self->prod_pkt.caplen = hdr.incl_len;
|
||||
self->prod_pkt.len = hdr.orig_len;
|
||||
|
||||
return (core_object_t*)&self->prod_pkt;
|
||||
}
|
||||
|
||||
core_producer_t input_zpcap_producer(input_zpcap_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
if (!self->file) {
|
||||
lfatal("no PCAP opened");
|
||||
}
|
||||
|
||||
return (core_producer_t)_produce;
|
||||
}
|
31
src/input/zpcap.h
Normal file
31
src/input/zpcap.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, OARC, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
#include <dnsjit/core/object/pcap.h>
|
||||
|
||||
#ifndef __dnsjit_input_zpcap_h
|
||||
#define __dnsjit_input_zpcap_h
|
||||
|
||||
#include <dnsjit/input/zpcap.hh>
|
||||
|
||||
#endif
|
77
src/input/zpcap.hh
Normal file
77
src/input/zpcap.hh
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, OARC, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//lua:require("dnsjit.core.log")
|
||||
//lua:require("dnsjit.core.receiver_h")
|
||||
//lua:require("dnsjit.core.producer_h")
|
||||
//lua:require("dnsjit.core.object.pcap_h")
|
||||
|
||||
typedef enum input_zpcap_type {
|
||||
input_zpcap_type_none,
|
||||
input_zpcap_type_lz4,
|
||||
input_zpcap_type_zstd
|
||||
} input_zpcap_type_t;
|
||||
|
||||
typedef struct input_zpcap {
|
||||
core_log_t _log;
|
||||
core_receiver_t recv;
|
||||
void* ctx;
|
||||
|
||||
uint8_t is_swapped;
|
||||
uint8_t is_nanosec;
|
||||
uint8_t is_broken;
|
||||
|
||||
core_object_pcap_t prod_pkt;
|
||||
|
||||
input_zpcap_type_t compression;
|
||||
void* comp_ctx;
|
||||
|
||||
void * in, *out;
|
||||
size_t in_size, out_size;
|
||||
size_t in_have, out_have;
|
||||
size_t in_at, out_at;
|
||||
|
||||
void* file;
|
||||
int extern_file, use_fadvise;
|
||||
size_t pkts;
|
||||
uint8_t* buf;
|
||||
size_t buf_size;
|
||||
|
||||
uint32_t magic_number;
|
||||
uint16_t version_major;
|
||||
uint16_t version_minor;
|
||||
int32_t thiszone;
|
||||
uint32_t sigfigs;
|
||||
uint32_t snaplen;
|
||||
uint32_t network;
|
||||
|
||||
uint32_t linktype;
|
||||
} input_zpcap_t;
|
||||
|
||||
core_log_t* input_zpcap_log();
|
||||
|
||||
void input_zpcap_init(input_zpcap_t* self);
|
||||
void input_zpcap_destroy(input_zpcap_t* self);
|
||||
int input_zpcap_open(input_zpcap_t* self, const char* file);
|
||||
int input_zpcap_openfp(input_zpcap_t* self, void* fp);
|
||||
int input_zpcap_run(input_zpcap_t* self);
|
||||
int input_zpcap_have_support(input_zpcap_t* self);
|
||||
|
||||
core_producer_t input_zpcap_producer(input_zpcap_t* self);
|
159
src/input/zpcap.lua
Normal file
159
src/input/zpcap.lua
Normal file
|
@ -0,0 +1,159 @@
|
|||
-- Copyright (c) 2018-2021, OARC, Inc.
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- This file is part of dnsjit.
|
||||
--
|
||||
-- dnsjit is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- dnsjit is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-- dnsjit.input.zpcap
|
||||
-- Read input from a PCAP file that is compressed
|
||||
-- local input = require("dnsjit.input.zpcap").new()
|
||||
-- input:zstd()
|
||||
-- input:open("file.pcap.zst")
|
||||
-- input:receiver(filter_or_output)
|
||||
-- input:run()
|
||||
--
|
||||
-- Read input from a PCAP file that is compressed and parse the PCAP without
|
||||
-- libpcap.
|
||||
-- After opening a file and reading the PCAP header, the attributes are
|
||||
-- populated.
|
||||
-- .SS Attributes
|
||||
-- .TP
|
||||
-- is_swapped
|
||||
-- Indicate if the byte order in the PCAP is in reverse order of the host.
|
||||
-- .TP
|
||||
-- is_nanosec
|
||||
-- Indicate if the time stamps are in nanoseconds or not.
|
||||
-- .TP
|
||||
-- magic_number
|
||||
-- Magic number.
|
||||
-- .TP
|
||||
-- version_major
|
||||
-- Major version number.
|
||||
-- .TP
|
||||
-- version_minor
|
||||
-- Minor version number.
|
||||
-- .TP
|
||||
-- thiszone
|
||||
-- GMT to local correction.
|
||||
-- .TP
|
||||
-- sigfigs
|
||||
-- Accuracy of timestamps.
|
||||
-- .TP
|
||||
-- snaplen
|
||||
-- Max length of captured packets, in octets.
|
||||
-- .TP
|
||||
-- network
|
||||
-- The link type found in the PCAP header, see https://www.tcpdump.org/linktypes.html .
|
||||
-- .TP
|
||||
-- linktype
|
||||
-- The data link type, mapped from
|
||||
-- .IR network .
|
||||
module(...,package.seeall)
|
||||
|
||||
require("dnsjit.input.zpcap_h")
|
||||
local ffi = require("ffi")
|
||||
local C = ffi.C
|
||||
|
||||
local t_name = "input_zpcap_t"
|
||||
local input_zpcap_t = ffi.typeof(t_name)
|
||||
local Zpcap = {}
|
||||
|
||||
-- Create a new Zpcap input.
|
||||
function Zpcap.new()
|
||||
local self = {
|
||||
_receiver = nil,
|
||||
obj = input_zpcap_t(),
|
||||
}
|
||||
C.input_zpcap_init(self.obj)
|
||||
ffi.gc(self.obj, C.input_zpcap_destroy)
|
||||
return setmetatable(self, { __index = Zpcap })
|
||||
end
|
||||
|
||||
-- Return the Log object to control logging of this instance or module.
|
||||
function Zpcap:log()
|
||||
if self == nil then
|
||||
return C.input_zpcap_log()
|
||||
end
|
||||
return self.obj._log
|
||||
end
|
||||
|
||||
-- Set the receiver to pass objects to.
|
||||
function Zpcap:receiver(o)
|
||||
self.obj.recv, self.obj.ctx = o:receive()
|
||||
self._receiver = o
|
||||
end
|
||||
|
||||
-- Return the C functions and context for producing objects.
|
||||
function Zpcap:produce()
|
||||
return C.input_zpcap_producer(self.obj), self.obj
|
||||
end
|
||||
|
||||
-- Use
|
||||
-- .B posix_fadvise()
|
||||
-- to indicate sequential reading (if supported), may increase performance.
|
||||
-- MUST be called before
|
||||
-- .BR open() .
|
||||
function Zpcap:fadvise_sequential()
|
||||
self.obj.use_fadvise = 1
|
||||
end
|
||||
|
||||
-- Use liblz4 to decompress the input file/data.
|
||||
function Zpcap:lz4()
|
||||
self.obj.compression = "input_zpcap_type_lz4"
|
||||
end
|
||||
|
||||
-- Use libzstd to decompress the input file/data.
|
||||
function Zpcap:zstd()
|
||||
self.obj.compression = "input_zpcap_type_zstd"
|
||||
end
|
||||
|
||||
-- Return true if support for selected compression library is built in.
|
||||
function Zpcap:have_support()
|
||||
if C.input_zpcap_have_support(self.obj) == 1 then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Open a PCAP file for processing and read the PCAP header.
|
||||
-- Returns 0 on success.
|
||||
function Zpcap:open(file)
|
||||
return C.input_zpcap_open(self.obj, file)
|
||||
end
|
||||
|
||||
-- Open a PCAP file for processing and read the PCAP header using a
|
||||
-- file descriptor, for example
|
||||
-- .B io.stdin
|
||||
-- or with
|
||||
-- .BR io.open() .
|
||||
-- Will not take ownership of the file descriptor.
|
||||
-- Returns 0 on success.
|
||||
function Zpcap:openfp(fp)
|
||||
return C.input_zpcap_openfp(self.obj, fp)
|
||||
end
|
||||
|
||||
-- Start processing packets and send each packet read to the receiver.
|
||||
-- Returns 0 if all packets was read successfully.
|
||||
function Zpcap:run()
|
||||
return C.input_zpcap_run(self.obj)
|
||||
end
|
||||
|
||||
-- Return the number of packets seen.
|
||||
function Zpcap:packets()
|
||||
return tonumber(self.obj.pkts)
|
||||
end
|
||||
|
||||
-- dnsjit.input.fpcap (3)
|
||||
return Zpcap
|
|
@ -23,6 +23,6 @@
|
|||
#ifndef __dnsjit_lib_base64url_h
|
||||
#define __dnsjit_lib_base64url_h
|
||||
|
||||
#include "lib/base64url.hh"
|
||||
#include <dnsjit/lib/base64url.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -93,6 +93,5 @@ function Base64Url.decode(data)
|
|||
return ffi.string(buf, out_len)
|
||||
end
|
||||
|
||||
-- dnsjit.core.object.payload(3)
|
||||
-- dnsjit.output.dnssim (3)
|
||||
-- dnsjit.core.object.payload (3)
|
||||
return Base64Url
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_lib_clock_h
|
||||
#define __dnsjit_lib_clock_h
|
||||
|
||||
#include "lib/clock.hh"
|
||||
#include <dnsjit/lib/clock.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -122,6 +122,9 @@ function Getopt:add(short, long, default, help, extensions)
|
|||
elseif name == "" then
|
||||
error("name (long|short) needs to be set")
|
||||
end
|
||||
if short and (type(short) ~= "string" or #short ~= 1) then
|
||||
error("short needs to be a string of length 1")
|
||||
end
|
||||
|
||||
if self._opt[name] then
|
||||
error("option "..name.." alredy exists")
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#ifndef __dnsjit_contrib_trie_h
|
||||
#define __dnsjit_contrib_trie_h
|
||||
|
||||
#include "lib/trie.hh"
|
||||
#include <dnsjit/lib/trie.hh>
|
||||
|
||||
#ifndef likely
|
||||
/*! \brief Optimize for x to be true value. */
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
module(...,package.seeall)
|
||||
|
||||
-- dnsjit.output.dnscli (3),
|
||||
-- dnsjit.output.dnssim (3),
|
||||
-- dnsjit.output.null (3),
|
||||
-- dnsjit.output.pcap (3),
|
||||
-- dnsjit.output.respdiff (3),
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#include "core/object/payload.h"
|
||||
#include "core/timespec.h"
|
||||
#include "core/compat.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
#include <dnsjit/core/object/payload.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
#include <dnsjit/core/compat.h>
|
||||
|
||||
#ifndef __dnsjit_output_dnscli_h
|
||||
#define __dnsjit_output_dnscli_h
|
||||
|
@ -33,6 +33,6 @@
|
|||
#include <gnutls/gnutls.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "output/dnscli.hh"
|
||||
#include <dnsjit/output/dnscli.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,502 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020, CZ.NIC, z.s.p.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "output/dnssim.h"
|
||||
#include "output/dnssim/internal.h"
|
||||
#include "output/dnssim/ll.h"
|
||||
#include "core/assert.h"
|
||||
#include "core/object/ip.h"
|
||||
#include "core/object/ip6.h"
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <string.h>
|
||||
|
||||
static core_log_t _log = LOG_T_INIT("output.dnssim");
|
||||
static output_dnssim_t _defaults = { LOG_T_INIT_OBJ("output.dnssim") };
|
||||
|
||||
static uint64_t _now_ms()
|
||||
{
|
||||
#if HAVE_CLOCK_NANOSLEEP
|
||||
struct timespec ts;
|
||||
uint64_t now_ms;
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts)) {
|
||||
mlfatal("clock_gettime()");
|
||||
}
|
||||
now_ms = ts.tv_sec * 1000;
|
||||
now_ms += ts.tv_nsec / 1000000;
|
||||
return now_ms;
|
||||
#else
|
||||
mlfatal("clock_gettime() not available");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
core_log_t* output_dnssim_log()
|
||||
{
|
||||
return &_log;
|
||||
}
|
||||
|
||||
output_dnssim_t* output_dnssim_new(size_t max_clients)
|
||||
{
|
||||
output_dnssim_t* self;
|
||||
int ret, i;
|
||||
|
||||
mlfatal_oom(self = calloc(1, sizeof(_output_dnssim_t)));
|
||||
*self = _defaults;
|
||||
self->handshake_timeout_ms = 5000;
|
||||
self->idle_timeout_ms = 10000;
|
||||
output_dnssim_timeout_ms(self, 2000);
|
||||
|
||||
_self->source = NULL;
|
||||
_self->transport = OUTPUT_DNSSIM_TRANSPORT_UDP_ONLY;
|
||||
_self->h2_zero_out_msgid = false;
|
||||
|
||||
self->max_clients = max_clients;
|
||||
lfatal_oom(_self->client_arr = calloc(max_clients, sizeof(_output_dnssim_client_t)));
|
||||
|
||||
for (i = 0; i < max_clients; ++i) {
|
||||
_self->client_arr[i].dnssim = self;
|
||||
}
|
||||
|
||||
ret = gnutls_certificate_allocate_credentials(&_self->tls_cred);
|
||||
if (ret < 0)
|
||||
lfatal("failed to allocated TLS credentials (%s)", gnutls_strerror(ret));
|
||||
|
||||
ret = uv_loop_init(&_self->loop);
|
||||
if (ret < 0)
|
||||
lfatal("failed to initialize uv_loop (%s)", uv_strerror(ret));
|
||||
ldebug("initialized uv_loop");
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void output_dnssim_free(output_dnssim_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
int ret, i;
|
||||
_output_dnssim_source_t* source;
|
||||
_output_dnssim_source_t* first = _self->source;
|
||||
output_dnssim_stats_t* stats_prev;
|
||||
|
||||
free(self->stats_sum->latency);
|
||||
free(self->stats_sum);
|
||||
do {
|
||||
stats_prev = self->stats_current->prev;
|
||||
free(self->stats_current->latency);
|
||||
free(self->stats_current);
|
||||
self->stats_current = stats_prev;
|
||||
} while (self->stats_current != NULL);
|
||||
|
||||
if (_self->source != NULL) {
|
||||
// free cilcular linked list
|
||||
do {
|
||||
source = _self->source->next;
|
||||
free(_self->source);
|
||||
_self->source = source;
|
||||
} while (_self->source != first);
|
||||
}
|
||||
|
||||
for (i = 0; i < self->max_clients; ++i) {
|
||||
if (_self->client_arr[i].tls_ticket.size != 0) {
|
||||
gnutls_free(_self->client_arr[i].tls_ticket.data);
|
||||
}
|
||||
}
|
||||
free(_self->client_arr);
|
||||
|
||||
ret = uv_loop_close(&_self->loop);
|
||||
if (ret < 0) {
|
||||
lcritical("failed to close uv_loop (%s)", uv_strerror(ret));
|
||||
} else {
|
||||
ldebug("closed uv_loop");
|
||||
}
|
||||
|
||||
gnutls_certificate_free_credentials(_self->tls_cred);
|
||||
if (_self->tls_priority != NULL) {
|
||||
gnutls_priority_deinit(*_self->tls_priority);
|
||||
free(_self->tls_priority);
|
||||
}
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
void output_dnssim_log_name(output_dnssim_t* self, const char* name)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(name, "name is nil");
|
||||
|
||||
strncpy(self->_log.name, name, sizeof(self->_log.name) - 1);
|
||||
self->_log.name[sizeof(self->_log.name) - 1] = 0;
|
||||
self->_log.is_obj = false;
|
||||
}
|
||||
|
||||
static uint32_t _extract_client(const core_object_t* obj)
|
||||
{
|
||||
uint32_t client;
|
||||
uint8_t* ip;
|
||||
|
||||
switch (obj->obj_type) {
|
||||
case CORE_OBJECT_IP:
|
||||
ip = ((core_object_ip_t*)obj)->dst;
|
||||
break;
|
||||
case CORE_OBJECT_IP6:
|
||||
ip = ((core_object_ip6_t*)obj)->dst;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&client, ip, sizeof(client));
|
||||
return client;
|
||||
}
|
||||
|
||||
static void _receive(output_dnssim_t* self, const core_object_t* obj)
|
||||
{
|
||||
mlassert_self();
|
||||
core_object_t* current = (core_object_t*)obj;
|
||||
core_object_payload_t* payload;
|
||||
uint32_t client;
|
||||
|
||||
self->processed++;
|
||||
|
||||
/* get payload from packet */
|
||||
for (;;) {
|
||||
if (current->obj_type == CORE_OBJECT_PAYLOAD) {
|
||||
payload = (core_object_payload_t*)current;
|
||||
break;
|
||||
}
|
||||
if (current->obj_prev == NULL) {
|
||||
self->discarded++;
|
||||
lwarning("packet discarded (missing payload object)");
|
||||
return;
|
||||
}
|
||||
current = (core_object_t*)current->obj_prev;
|
||||
}
|
||||
|
||||
/* extract client information from IP/IP6 layer */
|
||||
for (;;) {
|
||||
if (current->obj_type == CORE_OBJECT_IP || current->obj_type == CORE_OBJECT_IP6) {
|
||||
client = _extract_client(current);
|
||||
break;
|
||||
}
|
||||
if (current->obj_prev == NULL) {
|
||||
self->discarded++;
|
||||
lwarning("packet discarded (missing ip/ip6 object)");
|
||||
return;
|
||||
}
|
||||
current = (core_object_t*)current->obj_prev;
|
||||
}
|
||||
|
||||
if (self->free_after_use) {
|
||||
/* free all objects except payload */
|
||||
current = (core_object_t*)obj;
|
||||
core_object_t* parent = current;
|
||||
while (current != NULL) {
|
||||
parent = current;
|
||||
current = (core_object_t*)current->obj_prev;
|
||||
if (parent->obj_type != CORE_OBJECT_PAYLOAD) {
|
||||
core_object_free(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_self->h2_zero_out_msgid) {
|
||||
lassert(_self->transport == OUTPUT_DNSSIM_TRANSPORT_HTTPS2, "must use HTTP/2 to zero-out msgid");
|
||||
if (payload->len < 2) {
|
||||
self->discarded++;
|
||||
lwarning("packet discarded (payload len < 2)");
|
||||
return;
|
||||
}
|
||||
uint8_t* data = (uint8_t*)payload->payload;
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x00;
|
||||
}
|
||||
|
||||
if (client >= self->max_clients) {
|
||||
self->discarded++;
|
||||
lwarning("packet discarded (client exceeded max_clients)");
|
||||
return;
|
||||
}
|
||||
|
||||
ldebug("client(c): %d", client);
|
||||
_output_dnssim_create_request(self, &_self->client_arr[client], payload);
|
||||
}
|
||||
|
||||
core_receiver_t output_dnssim_receiver()
|
||||
{
|
||||
return (core_receiver_t)_receive;
|
||||
}
|
||||
|
||||
void output_dnssim_set_transport(output_dnssim_t* self, output_dnssim_transport_t tr)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
switch (tr) {
|
||||
case OUTPUT_DNSSIM_TRANSPORT_UDP_ONLY:
|
||||
lnotice("transport set to UDP (no TCP fallback)");
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TCP:
|
||||
lnotice("transport set to TCP");
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TLS:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
lnotice("transport set to TLS");
|
||||
#else
|
||||
lfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_HTTPS2:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
lnotice("transport set to HTTP/2 over TLS");
|
||||
if (&_self->h2_uri_authority[0])
|
||||
lnotice("set uri authority to: %s", _self->h2_uri_authority);
|
||||
#else
|
||||
lfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_UDP:
|
||||
lfatal("UDP transport with TCP fallback is not supported yet.");
|
||||
break;
|
||||
default:
|
||||
lfatal("unknown or unsupported transport");
|
||||
break;
|
||||
}
|
||||
|
||||
_self->transport = tr;
|
||||
}
|
||||
|
||||
int output_dnssim_target(output_dnssim_t* self, const char* ip, uint16_t port)
|
||||
{
|
||||
int ret;
|
||||
mlassert_self();
|
||||
lassert(ip, "ip is nil");
|
||||
lassert(port, "port is nil");
|
||||
|
||||
ret = uv_ip6_addr(ip, port, (struct sockaddr_in6*)&_self->target);
|
||||
if (ret != 0) {
|
||||
ret = uv_ip4_addr(ip, port, (struct sockaddr_in*)&_self->target);
|
||||
if (ret != 0) {
|
||||
lfatal("failed to parse IPv4 or IPv6 from \"%s\"", ip);
|
||||
} else {
|
||||
ret = snprintf(_self->h2_uri_authority, _MAX_URI_LEN, "%s:%d", ip, port);
|
||||
}
|
||||
} else {
|
||||
ret = snprintf(_self->h2_uri_authority, _MAX_URI_LEN, "[%s]:%d", ip, port);
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
if (_self->transport == OUTPUT_DNSSIM_TRANSPORT_HTTPS2)
|
||||
lnotice("set uri authority to: %s", _self->h2_uri_authority);
|
||||
} else {
|
||||
_self->h2_uri_authority[0] = '\0';
|
||||
if (_self->transport == OUTPUT_DNSSIM_TRANSPORT_HTTPS2)
|
||||
lfatal("failed to set authority");
|
||||
}
|
||||
|
||||
lnotice("set target to %s port %d", ip, port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int output_dnssim_bind(output_dnssim_t* self, const char* ip)
|
||||
{
|
||||
int ret;
|
||||
mlassert_self();
|
||||
lassert(ip, "ip is nil");
|
||||
|
||||
_output_dnssim_source_t* source;
|
||||
lfatal_oom(source = malloc(sizeof(_output_dnssim_source_t)));
|
||||
|
||||
ret = uv_ip6_addr(ip, 0, (struct sockaddr_in6*)&source->addr);
|
||||
if (ret != 0) {
|
||||
ret = uv_ip4_addr(ip, 0, (struct sockaddr_in*)&source->addr);
|
||||
if (ret != 0) {
|
||||
lfatal("failed to parse IPv4 or IPv6 from \"%s\"", ip);
|
||||
}
|
||||
}
|
||||
|
||||
if (_self->source == NULL) {
|
||||
source->next = source;
|
||||
_self->source = source;
|
||||
} else {
|
||||
source->next = _self->source->next;
|
||||
_self->source->next = source;
|
||||
}
|
||||
|
||||
lnotice("bind to source address %s", ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int output_dnssim_tls_priority(output_dnssim_t* self, const char* priority)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(priority, "priority is nil");
|
||||
|
||||
if (_self->tls_priority != NULL) {
|
||||
gnutls_priority_deinit(*_self->tls_priority);
|
||||
free(_self->tls_priority);
|
||||
}
|
||||
lfatal_oom(_self->tls_priority = malloc(sizeof(gnutls_priority_t)));
|
||||
|
||||
int ret = gnutls_priority_init(_self->tls_priority, priority, NULL);
|
||||
if (ret < 0) {
|
||||
lfatal("failed to initialize TLS priority cache: %s", gnutls_strerror(ret));
|
||||
} else {
|
||||
lnotice("GnuTLS priority set: %s", priority);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int output_dnssim_run_nowait(output_dnssim_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
return uv_run(&_self->loop, UV_RUN_NOWAIT);
|
||||
}
|
||||
|
||||
void output_dnssim_timeout_ms(output_dnssim_t* self, uint64_t timeout_ms)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(timeout_ms > 0, "timeout must be greater than 0");
|
||||
|
||||
if (self->stats_sum != NULL) {
|
||||
free(self->stats_sum->latency);
|
||||
free(self->stats_sum);
|
||||
self->stats_sum = 0;
|
||||
}
|
||||
if (self->stats_current != NULL) {
|
||||
output_dnssim_stats_t* stats_prev;
|
||||
do {
|
||||
stats_prev = self->stats_current->prev;
|
||||
free(self->stats_current->latency);
|
||||
free(self->stats_current);
|
||||
self->stats_current = stats_prev;
|
||||
} while (self->stats_current != NULL);
|
||||
}
|
||||
|
||||
self->timeout_ms = timeout_ms;
|
||||
|
||||
lfatal_oom(self->stats_sum = calloc(1, sizeof(output_dnssim_stats_t)));
|
||||
lfatal_oom(self->stats_sum->latency = calloc(self->timeout_ms + 1, sizeof(uint64_t)));
|
||||
|
||||
lfatal_oom(self->stats_current = calloc(1, sizeof(output_dnssim_stats_t)));
|
||||
lfatal_oom(self->stats_current->latency = calloc(self->timeout_ms + 1, sizeof(uint64_t)));
|
||||
|
||||
self->stats_first = self->stats_current;
|
||||
}
|
||||
|
||||
void output_dnssim_h2_uri_path(output_dnssim_t* self, const char* uri_path)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(uri_path, "uri_path is nil");
|
||||
lassert(strlen(uri_path) < _MAX_URI_LEN, "uri_path too long");
|
||||
|
||||
strncpy(_self->h2_uri_path, uri_path, _MAX_URI_LEN - 1);
|
||||
_self->h2_uri_path[_MAX_URI_LEN - 1] = 0;
|
||||
lnotice("http2: set uri path to: %s", _self->h2_uri_path);
|
||||
}
|
||||
|
||||
void output_dnssim_h2_method(output_dnssim_t* self, const char* method)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(method, "method is nil");
|
||||
|
||||
if (strcmp("GET", method) == 0) {
|
||||
_self->h2_method = OUTPUT_DNSSIM_H2_GET;
|
||||
} else if (strcmp("POST", method) == 0) {
|
||||
_self->h2_method = OUTPUT_DNSSIM_H2_POST;
|
||||
} else {
|
||||
lfatal("http2: unsupported method: \"%s\"", method);
|
||||
}
|
||||
|
||||
lnotice("http2: set method to %s", method);
|
||||
}
|
||||
|
||||
void output_dnssim_h2_zero_out_msgid(output_dnssim_t* self, bool zero_out_msgid)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
if (zero_out_msgid) {
|
||||
lassert(_self->transport == OUTPUT_DNSSIM_TRANSPORT_HTTPS2, "transport must be set to HTTP/2 to set zero_out_msgid");
|
||||
_self->h2_zero_out_msgid = zero_out_msgid;
|
||||
}
|
||||
}
|
||||
|
||||
static void _on_stats_timer_tick(uv_timer_t* handle)
|
||||
{
|
||||
uint64_t now_ms = _now_ms();
|
||||
output_dnssim_t* self;
|
||||
mlassert(handle, "handle is nil");
|
||||
self = (output_dnssim_t*)handle->data;
|
||||
mlassert_self();
|
||||
lassert(self->stats_sum, "stats_sum is nil");
|
||||
lassert(self->stats_current, "stats_current is nil");
|
||||
|
||||
lnotice("total processed:%10ld; answers:%10ld; discarded:%10ld; ongoing:%10ld",
|
||||
self->processed, self->stats_sum->answers, self->discarded, self->ongoing);
|
||||
|
||||
output_dnssim_stats_t* stats_next;
|
||||
lfatal_oom(stats_next = calloc(1, sizeof(output_dnssim_stats_t)));
|
||||
lfatal_oom(stats_next->latency = calloc(self->timeout_ms + 1, sizeof(uint64_t)));
|
||||
|
||||
self->stats_current->until_ms = now_ms;
|
||||
stats_next->since_ms = now_ms;
|
||||
stats_next->conn_active = self->stats_current->conn_active;
|
||||
|
||||
stats_next->ongoing = self->ongoing;
|
||||
stats_next->prev = self->stats_current;
|
||||
self->stats_current->next = stats_next;
|
||||
self->stats_current = stats_next;
|
||||
}
|
||||
|
||||
void output_dnssim_stats_collect(output_dnssim_t* self, uint64_t interval_ms)
|
||||
{
|
||||
uint64_t now_ms = _now_ms();
|
||||
mlassert_self();
|
||||
lassert(self->stats_sum, "stats_sum is nil");
|
||||
lassert(self->stats_current, "stats_current is nil");
|
||||
|
||||
if (self->stats_interval_ms != 0) {
|
||||
lfatal("statistics collection has already started!");
|
||||
}
|
||||
self->stats_interval_ms = interval_ms;
|
||||
|
||||
self->stats_sum->since_ms = now_ms;
|
||||
self->stats_current->since_ms = now_ms;
|
||||
|
||||
_self->stats_timer.data = (void*)self;
|
||||
uv_timer_init(&_self->loop, &_self->stats_timer);
|
||||
uv_timer_start(&_self->stats_timer, _on_stats_timer_tick, interval_ms, interval_ms);
|
||||
}
|
||||
|
||||
void output_dnssim_stats_finish(output_dnssim_t* self)
|
||||
{
|
||||
uint64_t now_ms = _now_ms();
|
||||
mlassert_self();
|
||||
lassert(self->stats_sum, "stats_sum is nil");
|
||||
lassert(self->stats_current, "stats_current is nil");
|
||||
|
||||
self->stats_sum->until_ms = now_ms;
|
||||
self->stats_current->until_ms = now_ms;
|
||||
|
||||
uv_timer_stop(&_self->stats_timer);
|
||||
uv_close((uv_handle_t*)&_self->stats_timer, NULL);
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, CZ.NIC, z.s.p.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//lua:require("dnsjit.core.log")
|
||||
//lua:require("dnsjit.core.receiver_h")
|
||||
|
||||
typedef enum output_dnssim_transport {
|
||||
OUTPUT_DNSSIM_TRANSPORT_UDP_ONLY,
|
||||
OUTPUT_DNSSIM_TRANSPORT_UDP,
|
||||
OUTPUT_DNSSIM_TRANSPORT_TCP,
|
||||
OUTPUT_DNSSIM_TRANSPORT_TLS,
|
||||
OUTPUT_DNSSIM_TRANSPORT_HTTPS2
|
||||
} output_dnssim_transport_t;
|
||||
|
||||
typedef enum output_dnssim_h2_method {
|
||||
OUTPUT_DNSSIM_H2_GET,
|
||||
OUTPUT_DNSSIM_H2_POST
|
||||
} output_dnssim_h2_method_t;
|
||||
|
||||
typedef struct output_dnssim_stats output_dnssim_stats_t;
|
||||
struct output_dnssim_stats {
|
||||
output_dnssim_stats_t* prev;
|
||||
output_dnssim_stats_t* next;
|
||||
|
||||
uint64_t* latency;
|
||||
|
||||
uint64_t since_ms;
|
||||
uint64_t until_ms;
|
||||
|
||||
uint64_t requests;
|
||||
uint64_t ongoing;
|
||||
uint64_t answers;
|
||||
|
||||
/* Number of connections that are open at the end of the stats interval. */
|
||||
uint64_t conn_active;
|
||||
|
||||
/* Number of connection handshake attempts during the stats interval. */
|
||||
uint64_t conn_handshakes;
|
||||
|
||||
/* Number of connection that have been resumed with TLS session resumption. */
|
||||
uint64_t conn_resumed;
|
||||
|
||||
/* Number of timed out connection handshakes during the stats interval. */
|
||||
uint64_t conn_handshakes_failed;
|
||||
|
||||
uint64_t rcode_noerror;
|
||||
uint64_t rcode_formerr;
|
||||
uint64_t rcode_servfail;
|
||||
uint64_t rcode_nxdomain;
|
||||
uint64_t rcode_notimp;
|
||||
uint64_t rcode_refused;
|
||||
uint64_t rcode_yxdomain;
|
||||
uint64_t rcode_yxrrset;
|
||||
uint64_t rcode_nxrrset;
|
||||
uint64_t rcode_notauth;
|
||||
uint64_t rcode_notzone;
|
||||
uint64_t rcode_badvers;
|
||||
uint64_t rcode_badkey;
|
||||
uint64_t rcode_badtime;
|
||||
uint64_t rcode_badmode;
|
||||
uint64_t rcode_badname;
|
||||
uint64_t rcode_badalg;
|
||||
uint64_t rcode_badtrunc;
|
||||
uint64_t rcode_badcookie;
|
||||
uint64_t rcode_other;
|
||||
};
|
||||
|
||||
typedef struct output_dnssim {
|
||||
core_log_t _log;
|
||||
|
||||
uint64_t processed;
|
||||
uint64_t discarded;
|
||||
uint64_t ongoing;
|
||||
|
||||
output_dnssim_stats_t* stats_sum;
|
||||
output_dnssim_stats_t* stats_current;
|
||||
output_dnssim_stats_t* stats_first;
|
||||
|
||||
size_t max_clients;
|
||||
bool free_after_use;
|
||||
|
||||
uint64_t timeout_ms;
|
||||
uint64_t idle_timeout_ms;
|
||||
uint64_t handshake_timeout_ms;
|
||||
uint64_t stats_interval_ms;
|
||||
} output_dnssim_t;
|
||||
|
||||
core_log_t* output_dnssim_log();
|
||||
|
||||
output_dnssim_t* output_dnssim_new(size_t max_clients);
|
||||
void output_dnssim_free(output_dnssim_t* self);
|
||||
|
||||
void output_dnssim_log_name(output_dnssim_t* self, const char* name);
|
||||
void output_dnssim_set_transport(output_dnssim_t* self, output_dnssim_transport_t tr);
|
||||
int output_dnssim_target(output_dnssim_t* self, const char* ip, uint16_t port);
|
||||
int output_dnssim_bind(output_dnssim_t* self, const char* ip);
|
||||
int output_dnssim_tls_priority(output_dnssim_t* self, const char* priority);
|
||||
int output_dnssim_run_nowait(output_dnssim_t* self);
|
||||
void output_dnssim_timeout_ms(output_dnssim_t* self, uint64_t timeout_ms);
|
||||
void output_dnssim_h2_uri_path(output_dnssim_t* self, const char* uri_path);
|
||||
void output_dnssim_h2_method(output_dnssim_t* self, const char* method);
|
||||
void output_dnssim_h2_zero_out_msgid(output_dnssim_t* self, bool zero_out_msgid);
|
||||
void output_dnssim_stats_collect(output_dnssim_t* self, uint64_t interval_ms);
|
||||
void output_dnssim_stats_finish(output_dnssim_t* self);
|
||||
|
||||
core_receiver_t output_dnssim_receiver();
|
|
@ -1,433 +0,0 @@
|
|||
-- Copyright (c) 2018-2021, CZ.NIC, z.s.p.o.
|
||||
-- All rights reserved.
|
||||
--
|
||||
-- This file is part of dnsjit.
|
||||
--
|
||||
-- dnsjit is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- dnsjit is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-- dnsjit.output.dnssim
|
||||
-- Simulate independent DNS clients over various transports
|
||||
-- output = require("dnsjit.output.dnssim").new()
|
||||
-- .SS Usage
|
||||
-- output:udp()
|
||||
-- output:target("::1", 53)
|
||||
-- recv, rctx = output:receive()
|
||||
-- -- pass in objects using recv(rctx, obj)
|
||||
-- -- repeatedly call output:run_nowait() until it returns 0
|
||||
-- .SS DNS-over-TLS example configuration
|
||||
-- output:tls("NORMAL:-VERS-ALL:+VERS-TLS1.3") -- enforce TLS 1.3
|
||||
-- .SS DNS-over-HTTPS/2 example configuration
|
||||
-- output:https2({ method = "POST", uri_path = "/doh" })
|
||||
--
|
||||
-- Output module for simulating traffic from huge number of independent,
|
||||
-- individual DNS clients.
|
||||
-- Uses libuv for asynchronous communication.
|
||||
-- There may only be a single DnsSim in a thread.
|
||||
-- Use
|
||||
-- .I dnsjit.core.thread
|
||||
-- to have multiple DnsSim instances.
|
||||
-- .P
|
||||
-- With proper use of this component, it is possible to simulate hundreds of
|
||||
-- thousands of clients when using a high-performance server.
|
||||
-- This also applies for state-full transports.
|
||||
-- The complete set-up is quite complex and requires other components.
|
||||
-- See DNS Shotgun
|
||||
-- .RI ( https://gitlab.nic.cz/knot/shotgun )
|
||||
-- for dnsjit scripts ready for use for high-performance
|
||||
-- benchmarking.
|
||||
module(...,package.seeall)
|
||||
|
||||
require("dnsjit.output.dnssim_h")
|
||||
local bit = require("bit")
|
||||
local object = require("dnsjit.core.objects")
|
||||
local ffi = require("ffi")
|
||||
local C = ffi.C
|
||||
|
||||
local DnsSim = {}
|
||||
|
||||
local _DNSSIM_VERSION = 20210129
|
||||
local _DNSSIM_JSON_VERSION = 20200527
|
||||
|
||||
-- Create a new DnsSim output for up to max_clients.
|
||||
function DnsSim.new(max_clients)
|
||||
local self = {
|
||||
obj = C.output_dnssim_new(max_clients),
|
||||
max_clients = max_clients,
|
||||
}
|
||||
ffi.gc(self.obj, C.output_dnssim_free)
|
||||
return setmetatable(self, { __index = DnsSim })
|
||||
end
|
||||
|
||||
local function _check_version(version, req_version)
|
||||
if req_version == nil then
|
||||
return version
|
||||
end
|
||||
local min_version = tonumber(req_version)
|
||||
if min_version == nil then
|
||||
C.output_dnssim_log():fatal("invalid version number: "..req_version)
|
||||
return nil
|
||||
end
|
||||
if version >= min_version then
|
||||
return version
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Check that version of dnssim is at minimum the one passed as
|
||||
-- .B req_version
|
||||
-- and return the actual version number.
|
||||
-- Return nil if the condition is not met.
|
||||
--
|
||||
-- If no
|
||||
-- .B req_version
|
||||
-- is specified no check is done and only the version number is returned.
|
||||
function DnsSim.check_version(req_version)
|
||||
return _check_version(_DNSSIM_VERSION, req_version)
|
||||
end
|
||||
|
||||
-- Check that version of dnssim's JSON data format is at minimum the one passed as
|
||||
-- .B req_version
|
||||
-- and return the actual version number.
|
||||
-- Return nil if the condition is not met.
|
||||
--
|
||||
-- If no
|
||||
-- .B req_version
|
||||
-- is specified no check is done and only the version number is returned.
|
||||
function DnsSim.check_json_version(req_version)
|
||||
return _check_version(_DNSSIM_JSON_VERSION, req_version)
|
||||
end
|
||||
|
||||
-- Return the Log object to control logging of this instance or module.
|
||||
-- Optionally, set the instance's log name.
|
||||
-- Unique name should be used for each instance.
|
||||
function DnsSim:log(name)
|
||||
if self == nil then
|
||||
return C.output_dnssim_log()
|
||||
end
|
||||
if name ~= nil then
|
||||
C.output_dnssim_log_name(self.obj, name)
|
||||
end
|
||||
return self.obj._log
|
||||
end
|
||||
|
||||
-- Set the target IPv4/IPv6 address where queries will be sent to.
|
||||
function DnsSim:target(ip, port)
|
||||
local nport = tonumber(port)
|
||||
if nport == nil then
|
||||
self.obj._log:fatal("invalid port: "..port)
|
||||
return -1
|
||||
end
|
||||
if nport <= 0 or nport > 65535 then
|
||||
self.obj._log:fatal("invalid port number: "..nport)
|
||||
return -1
|
||||
end
|
||||
return C.output_dnssim_target(self.obj, ip, nport)
|
||||
end
|
||||
|
||||
-- Specify source IPv4/IPv6 address for sending queries.
|
||||
-- Can be set multiple times.
|
||||
-- Addresses are selected round-robin when sending.
|
||||
function DnsSim:bind(ip)
|
||||
return C.output_dnssim_bind(self.obj, ip)
|
||||
end
|
||||
|
||||
-- Set the preferred transport to UDP.
|
||||
--
|
||||
-- When the optional argument
|
||||
-- .B tcp_fallback
|
||||
-- is set to true, individual queries are re-tried over TCP when TC bit is set in the answer.
|
||||
-- Defaults to
|
||||
-- .B false
|
||||
-- (aka only UDP is used).
|
||||
function DnsSim:udp(tcp_fallback)
|
||||
if tcp_fallback == true then
|
||||
C.output_dnssim_set_transport(self.obj, C.OUTPUT_DNSSIM_TRANSPORT_UDP)
|
||||
else
|
||||
C.output_dnssim_set_transport(self.obj, C.OUTPUT_DNSSIM_TRANSPORT_UDP_ONLY)
|
||||
end
|
||||
end
|
||||
|
||||
-- Set the transport to TCP.
|
||||
function DnsSim:tcp()
|
||||
C.output_dnssim_set_transport(self.obj, C.OUTPUT_DNSSIM_TRANSPORT_TCP)
|
||||
end
|
||||
|
||||
-- Set the transport to TLS.
|
||||
--
|
||||
-- The optional argument
|
||||
-- .B tls_priority
|
||||
-- is a GnuTLS priority string, which can be used to select TLS versions, cipher suites etc.
|
||||
-- For example:
|
||||
--
|
||||
-- .RB "- """ NORMAL:%NO_TICKETS """"
|
||||
-- will use defaults without TLS session resumption.
|
||||
--
|
||||
-- .RB "- """ SECURE128:-VERS-ALL:+VERS-TLS1.3 """"
|
||||
-- will use only TLS 1.3 with 128-bit secure ciphers.
|
||||
--
|
||||
-- Refer to:
|
||||
-- .I https://gnutls.org/manual/html_node/Priority-Strings.html
|
||||
function DnsSim:tls(tls_priority)
|
||||
if tls_priority ~= nil then
|
||||
C.output_dnssim_tls_priority(self.obj, tls_priority)
|
||||
end
|
||||
C.output_dnssim_set_transport(self.obj, C.OUTPUT_DNSSIM_TRANSPORT_TLS)
|
||||
end
|
||||
|
||||
-- Set the transport to HTTP/2 over TLS.
|
||||
--
|
||||
-- .B http2_options
|
||||
-- is a lua table which supports the following keys:
|
||||
--
|
||||
-- .B method:
|
||||
-- .B GET
|
||||
-- (default)
|
||||
-- or
|
||||
-- .B POST
|
||||
--
|
||||
-- .B uri_path:
|
||||
-- where queries will be sent.
|
||||
-- Defaults to
|
||||
-- .B /dns-query
|
||||
--
|
||||
-- .B zero_out_msgid:
|
||||
-- when
|
||||
-- .B true
|
||||
-- (default), query ID is always set to 0
|
||||
--
|
||||
-- See tls() method for
|
||||
-- .B tls_priority
|
||||
-- documentation.
|
||||
function DnsSim:https2(http2_options, tls_priority)
|
||||
if tls_priority ~= nil then
|
||||
C.output_dnssim_tls_priority(self.obj, tls_priority)
|
||||
end
|
||||
|
||||
uri_path = "/dns-query"
|
||||
zero_out_msgid = true
|
||||
method = "GET"
|
||||
|
||||
if http2_options ~= nil then
|
||||
if type(http2_options) ~= "table" then
|
||||
self.obj._log:fatal("http2_options must be a table")
|
||||
else
|
||||
if http2_options["uri_path"] ~= nil then
|
||||
uri_path = http2_options["uri_path"]
|
||||
end
|
||||
if http2_options["zero_out_msgid"] ~= nil and http2_options["zero_out_msgid"] ~= true then
|
||||
zero_out_msgid = false
|
||||
end
|
||||
if http2_options["method"] ~= nil then
|
||||
method = http2_options["method"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
C.output_dnssim_set_transport(self.obj, C.OUTPUT_DNSSIM_TRANSPORT_HTTPS2)
|
||||
C.output_dnssim_h2_uri_path(self.obj, uri_path)
|
||||
C.output_dnssim_h2_method(self.obj, method)
|
||||
C.output_dnssim_h2_zero_out_msgid(self.obj, zero_out_msgid)
|
||||
end
|
||||
|
||||
-- Set timeout for the individual requests in seconds (default 2s).
|
||||
--
|
||||
-- .BR Beware :
|
||||
-- increasing this value while the target resolver isn't very responsive
|
||||
-- (cold cache, heavy load) may degrade DnsSim's performance and skew
|
||||
-- the results.
|
||||
function DnsSim:timeout(seconds)
|
||||
if seconds == nil then
|
||||
seconds = 2
|
||||
end
|
||||
timeout_ms = math.floor(seconds * 1000)
|
||||
C.output_dnssim_timeout_ms(self.obj, timeout_ms)
|
||||
end
|
||||
|
||||
-- Set TCP connection idle timeout for connection reuse according to RFC7766,
|
||||
-- Section 6.2.3 (defaults to 10s).
|
||||
-- When set to zero, connections are closed immediately after there are no
|
||||
-- more pending queries.
|
||||
function DnsSim:idle_timeout(seconds)
|
||||
if seconds == nil then
|
||||
seconds = 10
|
||||
end
|
||||
self.obj.idle_timeout_ms = math.floor(seconds * 1000)
|
||||
end
|
||||
|
||||
-- Set TCP connection handshake timeout (defaults to 5s).
|
||||
-- During heavy load, the server may no longer accept new connections.
|
||||
-- This parameter ensures such connection attempts are aborted after the
|
||||
-- timeout expires.
|
||||
function DnsSim:handshake_timeout(seconds)
|
||||
if seconds == nil then
|
||||
seconds = 5
|
||||
end
|
||||
self.obj.handshake_timeout_ms = math.floor(seconds * 1000)
|
||||
end
|
||||
|
||||
-- Run the libuv loop once without blocking when there is no I/O.
|
||||
-- This should be called repeatedly until 0 is returned and no more data
|
||||
-- is expected to be received by DnsSim.
|
||||
function DnsSim:run_nowait()
|
||||
return C.output_dnssim_run_nowait(self.obj)
|
||||
end
|
||||
|
||||
-- Set this to true if DnsSim should free the memory of passed-in objects
|
||||
-- (useful when using
|
||||
-- .I dnsjit.filter.copy
|
||||
-- to pass objects from different thread).
|
||||
function DnsSim:free_after_use(free_after_use)
|
||||
self.obj.free_after_use = free_after_use
|
||||
end
|
||||
|
||||
-- Number of input packets discarded due to various reasons.
|
||||
-- To investigate causes, run with increased logging level.
|
||||
function DnsSim:discarded()
|
||||
return tonumber(self.obj.discarded)
|
||||
end
|
||||
|
||||
-- Number of valid requests (input packets) processed.
|
||||
function DnsSim:requests()
|
||||
return tonumber(self.obj.stats_sum.requests)
|
||||
end
|
||||
|
||||
-- Number of requests that received an answer
|
||||
function DnsSim:answers()
|
||||
return tonumber(self.obj.stats_sum.answers)
|
||||
end
|
||||
|
||||
-- Number of requests that received a NOERROR response
|
||||
function DnsSim:noerror()
|
||||
return tonumber(self.obj.stats_sum.rcode_noerror)
|
||||
end
|
||||
|
||||
-- Configure statistics to be collected every N seconds.
|
||||
function DnsSim:stats_collect(seconds)
|
||||
if seconds == nil then
|
||||
self.obj._log:fatal("number of seconds must be set for stats_collect()")
|
||||
end
|
||||
interval_ms = math.floor(seconds * 1000)
|
||||
C.output_dnssim_stats_collect(self.obj, interval_ms)
|
||||
end
|
||||
|
||||
-- Stop the collection of statistics.
|
||||
function DnsSim:stats_finish()
|
||||
C.output_dnssim_stats_finish(self.obj)
|
||||
end
|
||||
|
||||
-- Export the results to a JSON file.
|
||||
function DnsSim:export(filename)
|
||||
local file = io.open(filename, "w")
|
||||
if file == nil then
|
||||
self.obj._log:fatal("export failed: no filename")
|
||||
return
|
||||
end
|
||||
|
||||
local function write_stats(file, stats)
|
||||
file:write(
|
||||
"{ ",
|
||||
'"since_ms":', tonumber(stats.since_ms), ',',
|
||||
'"until_ms":', tonumber(stats.until_ms), ',',
|
||||
'"requests":', tonumber(stats.requests), ',',
|
||||
'"ongoing":', tonumber(stats.ongoing), ',',
|
||||
'"answers":', tonumber(stats.answers), ',',
|
||||
'"conn_active":', tonumber(stats.conn_active), ',',
|
||||
'"conn_handshakes":', tonumber(stats.conn_handshakes), ',',
|
||||
'"conn_resumed":', tonumber(stats.conn_resumed), ',',
|
||||
'"conn_handshakes_failed":', tonumber(stats.conn_handshakes_failed), ',',
|
||||
'"rcode_noerror":', tonumber(stats.rcode_noerror), ',',
|
||||
'"rcode_formerr":', tonumber(stats.rcode_formerr), ',',
|
||||
'"rcode_servfail":', tonumber(stats.rcode_servfail), ',',
|
||||
'"rcode_nxdomain":', tonumber(stats.rcode_nxdomain), ',',
|
||||
'"rcode_notimp":', tonumber(stats.rcode_notimp), ',',
|
||||
'"rcode_refused":', tonumber(stats.rcode_refused), ',',
|
||||
'"rcode_yxdomain":', tonumber(stats.rcode_yxdomain), ',',
|
||||
'"rcode_yxrrset":', tonumber(stats.rcode_yxrrset), ',',
|
||||
'"rcode_nxrrset":', tonumber(stats.rcode_nxrrset), ',',
|
||||
'"rcode_notauth":', tonumber(stats.rcode_notauth), ',',
|
||||
'"rcode_notzone":', tonumber(stats.rcode_notzone), ',',
|
||||
'"rcode_badvers":', tonumber(stats.rcode_badvers), ',',
|
||||
'"rcode_badkey":', tonumber(stats.rcode_badkey), ',',
|
||||
'"rcode_badtime":', tonumber(stats.rcode_badtime), ',',
|
||||
'"rcode_badmode":', tonumber(stats.rcode_badmode), ',',
|
||||
'"rcode_badname":', tonumber(stats.rcode_badname), ',',
|
||||
'"rcode_badalg":', tonumber(stats.rcode_badalg), ',',
|
||||
'"rcode_badtrunc":', tonumber(stats.rcode_badtrunc), ',',
|
||||
'"rcode_badcookie":', tonumber(stats.rcode_badcookie), ',',
|
||||
'"rcode_other":', tonumber(stats.rcode_other), ',',
|
||||
'"latency":[')
|
||||
file:write(tonumber(stats.latency[0]))
|
||||
for i=1,tonumber(self.obj.timeout_ms) do
|
||||
file:write(',', tonumber(stats.latency[i]))
|
||||
end
|
||||
file:write("]}")
|
||||
end
|
||||
|
||||
file:write(
|
||||
"{ ",
|
||||
'"version":', _DNSSIM_JSON_VERSION, ',',
|
||||
'"merged":false,',
|
||||
'"stats_interval_ms":', tonumber(self.obj.stats_interval_ms), ',',
|
||||
'"timeout_ms":', tonumber(self.obj.timeout_ms), ',',
|
||||
'"idle_timeout_ms":', tonumber(self.obj.idle_timeout_ms), ',',
|
||||
'"handshake_timeout_ms":', tonumber(self.obj.handshake_timeout_ms), ',',
|
||||
'"discarded":', self:discarded(), ',',
|
||||
'"stats_sum":')
|
||||
write_stats(file, self.obj.stats_sum)
|
||||
file:write(
|
||||
',',
|
||||
'"stats_periodic":[')
|
||||
|
||||
local stats = self.obj.stats_first
|
||||
write_stats(file, stats)
|
||||
|
||||
while (stats.next ~= nil) do
|
||||
stats = stats.next
|
||||
file:write(',')
|
||||
write_stats(file, stats)
|
||||
end
|
||||
|
||||
file:write(']}')
|
||||
file:close()
|
||||
self.obj._log:notice("results exported to "..filename)
|
||||
end
|
||||
|
||||
-- Return the C function and context for receiving objects.
|
||||
-- Only
|
||||
-- .I dnsjit.filter.core.object.ip
|
||||
-- or
|
||||
-- .I dnsjit.filter.core.object.ip6
|
||||
-- objects are supported.
|
||||
-- The component expects a 32bit integer (in host order) ranging from 0
|
||||
-- to max_clients written to first 4 bytes of destination IP.
|
||||
-- See
|
||||
-- .IR dnsjit.filter.ipsplit .
|
||||
function DnsSim:receive()
|
||||
local receive = C.output_dnssim_receiver()
|
||||
return receive, self.obj
|
||||
end
|
||||
|
||||
-- Deprecated: use udp() instead.
|
||||
--
|
||||
-- Set the transport to UDP (without any TCP fallback).
|
||||
function DnsSim:udp_only()
|
||||
C.output_dnssim_set_transport(self.obj, C.OUTPUT_DNSSIM_TRANSPORT_UDP_ONLY)
|
||||
end
|
||||
|
||||
-- dnsjit.filter.copy (3),
|
||||
-- dnsjit.filter.ipsplit (3),
|
||||
-- dnsjit.filter.core.object.ip (3),
|
||||
-- dnsjit.filter.core.object.ip6 (3),
|
||||
-- https://gitlab.nic.cz/knot/shotgun
|
||||
return DnsSim
|
|
@ -1,16 +0,0 @@
|
|||
dnssim v20210129
|
||||
================
|
||||
|
||||
- Added DNS-over-HTTPS support with https2()
|
||||
- Added IPv4 support
|
||||
- Abort operation on insufficient file descriptors
|
||||
- Match QUESTION section of received responses
|
||||
- Improvements in connection state handling
|
||||
- Deprecate udp_only() in favor of udp()
|
||||
- Allow setting logger name with log(name)
|
||||
- Added check_version() and check_json_version()
|
||||
|
||||
dnssim v20200723
|
||||
================
|
||||
|
||||
- First released dnssim version with UDP, TCP and DoT support
|
|
@ -1,384 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020, CZ.NIC, z.s.p.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "output/dnssim.h"
|
||||
#include "output/dnssim/internal.h"
|
||||
#include "output/dnssim/ll.h"
|
||||
#include "core/assert.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_LABELS 127
|
||||
|
||||
static core_log_t _log = LOG_T_INIT("output.dnssim");
|
||||
|
||||
static void _close_request(_output_dnssim_request_t* req);
|
||||
|
||||
static void _on_request_timeout(uv_timer_t* handle)
|
||||
{
|
||||
_close_request((_output_dnssim_request_t*)handle->data);
|
||||
}
|
||||
|
||||
static ssize_t parse_qsection(core_object_dns_t* dns)
|
||||
{
|
||||
core_object_dns_q_t q;
|
||||
static core_object_dns_label_t labels[MAX_LABELS];
|
||||
const uint8_t* start;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (!dns || !dns->have_qdcount)
|
||||
return -1;
|
||||
|
||||
start = dns->at;
|
||||
|
||||
for (i = 0; i < dns->qdcount; i++) {
|
||||
ret = core_object_dns_parse_q(dns, &q, labels, MAX_LABELS);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (dns->at - start);
|
||||
}
|
||||
|
||||
int _output_dnssim_answers_request(_output_dnssim_request_t* req, core_object_dns_t* response)
|
||||
{
|
||||
const uint8_t* question;
|
||||
ssize_t len;
|
||||
|
||||
if (!response->have_id || !response->have_qdcount)
|
||||
return _ERR_MALFORMED;
|
||||
|
||||
if (req->dns_q->id != response->id)
|
||||
return _ERR_MSGID;
|
||||
|
||||
if (req->dns_q->qdcount != response->qdcount)
|
||||
return _ERR_QUESTION;
|
||||
|
||||
question = response->at;
|
||||
len = parse_qsection(response);
|
||||
|
||||
if (req->question_len != len)
|
||||
return _ERR_QUESTION;
|
||||
|
||||
if (memcmp(req->question, question, len) != 0)
|
||||
return _ERR_QUESTION;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _output_dnssim_create_request(output_dnssim_t* self, _output_dnssim_client_t* client, core_object_payload_t* payload)
|
||||
{
|
||||
int ret;
|
||||
_output_dnssim_request_t* req;
|
||||
mlassert_self();
|
||||
lassert(client, "client is nil");
|
||||
lassert(payload, "payload is nil");
|
||||
|
||||
lfatal_oom(req = calloc(1, sizeof(_output_dnssim_request_t)));
|
||||
req->dnssim = self;
|
||||
req->client = client;
|
||||
req->payload = payload;
|
||||
req->dns_q = core_object_dns_new();
|
||||
req->dns_q->obj_prev = (core_object_t*)req->payload;
|
||||
req->dnssim->ongoing++;
|
||||
req->state = _OUTPUT_DNSSIM_REQ_ONGOING;
|
||||
req->stats = self->stats_current;
|
||||
|
||||
ret = core_object_dns_parse_header(req->dns_q);
|
||||
if (ret != 0) {
|
||||
ldebug("discarded malformed dns query: couldn't parse header");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
req->question = req->dns_q->at;
|
||||
req->question_len = parse_qsection(req->dns_q);
|
||||
if (req->question_len < 0) {
|
||||
ldebug("discarded malformed dns query: invalid question");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
req->dnssim->stats_sum->requests++;
|
||||
req->stats->requests++;
|
||||
|
||||
switch (_self->transport) {
|
||||
case OUTPUT_DNSSIM_TRANSPORT_UDP_ONLY:
|
||||
case OUTPUT_DNSSIM_TRANSPORT_UDP:
|
||||
ret = _output_dnssim_create_query_udp(self, req);
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TCP:
|
||||
ret = _output_dnssim_create_query_tcp(self, req);
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TLS:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
ret = _output_dnssim_create_query_tls(self, req);
|
||||
#else
|
||||
lfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_HTTPS2:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
ret = _output_dnssim_create_query_https2(self, req);
|
||||
#else
|
||||
lfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
lfatal("unsupported dnssim transport");
|
||||
break;
|
||||
}
|
||||
if (ret < 0) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
req->created_at = uv_now(&_self->loop);
|
||||
req->ended_at = req->created_at + self->timeout_ms;
|
||||
lfatal_oom(req->timer = malloc(sizeof(uv_timer_t)));
|
||||
uv_timer_init(&_self->loop, req->timer);
|
||||
req->timer->data = req;
|
||||
uv_timer_start(req->timer, _on_request_timeout, self->timeout_ms, 0);
|
||||
|
||||
return;
|
||||
failure:
|
||||
self->discarded++;
|
||||
_close_request(req);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Bind before connect to be able to send from different source IPs. */
|
||||
int _output_dnssim_bind_before_connect(output_dnssim_t* self, uv_handle_t* handle)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(handle, "handle is nil");
|
||||
|
||||
if (_self->source != NULL) {
|
||||
struct sockaddr* addr = (struct sockaddr*)&_self->source->addr;
|
||||
struct sockaddr* dest = (struct sockaddr*)&_self->target;
|
||||
int ret = -1;
|
||||
if (addr->sa_family != dest->sa_family) {
|
||||
lfatal("failed to bind: source/desitnation address family mismatch");
|
||||
}
|
||||
switch (handle->type) {
|
||||
case UV_UDP:
|
||||
ret = uv_udp_bind((uv_udp_t*)handle, addr, 0);
|
||||
break;
|
||||
case UV_TCP:
|
||||
ret = uv_tcp_bind((uv_tcp_t*)handle, addr, 0);
|
||||
break;
|
||||
default:
|
||||
lfatal("failed to bind: unsupported handle type");
|
||||
break;
|
||||
}
|
||||
if (ret < 0) {
|
||||
/* This typically happens when we run out of file descriptors.
|
||||
* Quit to prevent skewed results or unexpected behaviour. */
|
||||
lfatal("failed to bind: %s", uv_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
_self->source = _self->source->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _output_dnssim_maybe_free_request(_output_dnssim_request_t* req)
|
||||
{
|
||||
mlassert(req, "req is nil");
|
||||
|
||||
if (req->qry == NULL && req->timer == NULL) {
|
||||
if (req->dnssim->free_after_use) {
|
||||
core_object_payload_free(req->payload);
|
||||
}
|
||||
core_object_dns_free(req->dns_q);
|
||||
free(req);
|
||||
}
|
||||
}
|
||||
|
||||
static void _close_query(_output_dnssim_query_t* qry)
|
||||
{
|
||||
mlassert(qry, "qry is nil");
|
||||
|
||||
switch (qry->transport) {
|
||||
case OUTPUT_DNSSIM_TRANSPORT_UDP:
|
||||
_output_dnssim_close_query_udp((_output_dnssim_query_udp_t*)qry);
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TCP:
|
||||
_output_dnssim_close_query_tcp((_output_dnssim_query_tcp_t*)qry);
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TLS:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
_output_dnssim_close_query_tls((_output_dnssim_query_tcp_t*)qry);
|
||||
#else
|
||||
mlfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_HTTPS2:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
_output_dnssim_close_query_https2((_output_dnssim_query_tcp_t*)qry);
|
||||
#else
|
||||
mlfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
mlfatal("invalid query transport");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _on_request_timer_closed(uv_handle_t* handle)
|
||||
{
|
||||
_output_dnssim_request_t* req = (_output_dnssim_request_t*)handle->data;
|
||||
mlassert(req, "req is nil");
|
||||
free(handle);
|
||||
req->timer = NULL;
|
||||
_output_dnssim_maybe_free_request(req);
|
||||
}
|
||||
|
||||
static void _close_request(_output_dnssim_request_t* req)
|
||||
{
|
||||
if (req == NULL || req->state == _OUTPUT_DNSSIM_REQ_CLOSING)
|
||||
return;
|
||||
mlassert(req->state == _OUTPUT_DNSSIM_REQ_ONGOING, "request to be closed must be ongoing");
|
||||
req->state = _OUTPUT_DNSSIM_REQ_CLOSING;
|
||||
req->dnssim->ongoing--;
|
||||
|
||||
/* Calculate latency. */
|
||||
uint64_t latency;
|
||||
req->ended_at = uv_now(&((_output_dnssim_t*)req->dnssim)->loop);
|
||||
latency = req->ended_at - req->created_at;
|
||||
if (latency > req->dnssim->timeout_ms) {
|
||||
req->ended_at = req->created_at + req->dnssim->timeout_ms;
|
||||
latency = req->dnssim->timeout_ms;
|
||||
}
|
||||
req->stats->latency[latency]++;
|
||||
req->dnssim->stats_sum->latency[latency]++;
|
||||
|
||||
if (req->timer != NULL) {
|
||||
uv_timer_stop(req->timer);
|
||||
uv_close((uv_handle_t*)req->timer, _on_request_timer_closed);
|
||||
}
|
||||
|
||||
/* Finish any queries in flight. */
|
||||
_output_dnssim_query_t* qry = req->qry;
|
||||
if (qry != NULL)
|
||||
_close_query(qry);
|
||||
|
||||
_output_dnssim_maybe_free_request(req);
|
||||
}
|
||||
|
||||
void _output_dnssim_request_answered(_output_dnssim_request_t* req, core_object_dns_t* msg)
|
||||
{
|
||||
mlassert(req, "req is nil");
|
||||
mlassert(msg, "msg is nil");
|
||||
|
||||
req->dnssim->stats_sum->answers++;
|
||||
req->stats->answers++;
|
||||
|
||||
switch (msg->rcode) {
|
||||
case CORE_OBJECT_DNS_RCODE_NOERROR:
|
||||
req->dnssim->stats_sum->rcode_noerror++;
|
||||
req->stats->rcode_noerror++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_FORMERR:
|
||||
req->dnssim->stats_sum->rcode_formerr++;
|
||||
req->stats->rcode_formerr++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_SERVFAIL:
|
||||
req->dnssim->stats_sum->rcode_servfail++;
|
||||
req->stats->rcode_servfail++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_NXDOMAIN:
|
||||
req->dnssim->stats_sum->rcode_nxdomain++;
|
||||
req->stats->rcode_nxdomain++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_NOTIMP:
|
||||
req->dnssim->stats_sum->rcode_notimp++;
|
||||
req->stats->rcode_notimp++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_REFUSED:
|
||||
req->dnssim->stats_sum->rcode_refused++;
|
||||
req->stats->rcode_refused++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_YXDOMAIN:
|
||||
req->dnssim->stats_sum->rcode_yxdomain++;
|
||||
req->stats->rcode_yxdomain++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_YXRRSET:
|
||||
req->dnssim->stats_sum->rcode_yxrrset++;
|
||||
req->stats->rcode_yxrrset++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_NXRRSET:
|
||||
req->dnssim->stats_sum->rcode_nxrrset++;
|
||||
req->stats->rcode_nxrrset++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_NOTAUTH:
|
||||
req->dnssim->stats_sum->rcode_notauth++;
|
||||
req->stats->rcode_notauth++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_NOTZONE:
|
||||
req->dnssim->stats_sum->rcode_notzone++;
|
||||
req->stats->rcode_notzone++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_BADVERS:
|
||||
req->dnssim->stats_sum->rcode_badvers++;
|
||||
req->stats->rcode_badvers++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_BADKEY:
|
||||
req->dnssim->stats_sum->rcode_badkey++;
|
||||
req->stats->rcode_badkey++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_BADTIME:
|
||||
req->dnssim->stats_sum->rcode_badtime++;
|
||||
req->stats->rcode_badtime++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_BADMODE:
|
||||
req->dnssim->stats_sum->rcode_badmode++;
|
||||
req->stats->rcode_badmode++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_BADNAME:
|
||||
req->dnssim->stats_sum->rcode_badname++;
|
||||
req->stats->rcode_badname++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_BADALG:
|
||||
req->dnssim->stats_sum->rcode_badalg++;
|
||||
req->stats->rcode_badalg++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_BADTRUNC:
|
||||
req->dnssim->stats_sum->rcode_badtrunc++;
|
||||
req->stats->rcode_badtrunc++;
|
||||
break;
|
||||
case CORE_OBJECT_DNS_RCODE_BADCOOKIE:
|
||||
req->dnssim->stats_sum->rcode_badcookie++;
|
||||
req->stats->rcode_badcookie++;
|
||||
break;
|
||||
default:
|
||||
req->dnssim->stats_sum->rcode_other++;
|
||||
req->stats->rcode_other++;
|
||||
}
|
||||
|
||||
_close_request(req);
|
||||
}
|
||||
|
||||
void _output_dnssim_on_uv_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
|
||||
{
|
||||
mlfatal_oom(buf->base = malloc(suggested_size));
|
||||
buf->len = suggested_size;
|
||||
}
|
|
@ -1,471 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020, CZ.NIC, z.s.p.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "output/dnssim.h"
|
||||
#include "output/dnssim/internal.h"
|
||||
#include "output/dnssim/ll.h"
|
||||
#include "core/assert.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static core_log_t _log = LOG_T_INIT("output.dnssim");
|
||||
|
||||
static bool _conn_is_connecting(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
return (conn->state >= _OUTPUT_DNSSIM_CONN_TCP_HANDSHAKE && conn->state <= _OUTPUT_DNSSIM_CONN_ACTIVE);
|
||||
}
|
||||
|
||||
void _output_dnssim_conn_maybe_free(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn can't be nil");
|
||||
mlassert(conn->client, "conn must belong to a client");
|
||||
if (conn->handle == NULL && conn->handshake_timer == NULL && conn->idle_timer == NULL) {
|
||||
_ll_try_remove(conn->client->conn, conn);
|
||||
if (conn->tls != NULL) {
|
||||
free(conn->tls);
|
||||
conn->tls = NULL;
|
||||
}
|
||||
if (conn->http2 != NULL) {
|
||||
free(conn->http2);
|
||||
conn->http2 = NULL;
|
||||
}
|
||||
free(conn);
|
||||
}
|
||||
}
|
||||
|
||||
static void _on_handshake_timer_closed(uv_handle_t* handle)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)handle->data;
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->handshake_timer, "conn must have handshake timer when closing it");
|
||||
free(conn->handshake_timer);
|
||||
conn->handshake_timer = NULL;
|
||||
_output_dnssim_conn_maybe_free(conn);
|
||||
}
|
||||
|
||||
static void _on_idle_timer_closed(uv_handle_t* handle)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)handle->data;
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->idle_timer, "conn must have idle timer when closing it");
|
||||
free(conn->idle_timer);
|
||||
conn->is_idle = false;
|
||||
conn->idle_timer = NULL;
|
||||
_output_dnssim_conn_maybe_free(conn);
|
||||
}
|
||||
|
||||
void _output_dnssim_conn_close(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn can't be nil");
|
||||
mlassert(conn->stats, "conn must have stats");
|
||||
mlassert(conn->client, "conn must have client");
|
||||
mlassert(conn->client->dnssim, "client must have dnssim");
|
||||
|
||||
output_dnssim_t* self = conn->client->dnssim;
|
||||
|
||||
switch (conn->state) {
|
||||
case _OUTPUT_DNSSIM_CONN_CLOSING:
|
||||
case _OUTPUT_DNSSIM_CONN_CLOSED:
|
||||
return;
|
||||
case _OUTPUT_DNSSIM_CONN_TCP_HANDSHAKE:
|
||||
case _OUTPUT_DNSSIM_CONN_TLS_HANDSHAKE:
|
||||
conn->stats->conn_handshakes_failed++;
|
||||
self->stats_sum->conn_handshakes_failed++;
|
||||
break;
|
||||
case _OUTPUT_DNSSIM_CONN_ACTIVE:
|
||||
case _OUTPUT_DNSSIM_CONN_CONGESTED:
|
||||
self->stats_current->conn_active--;
|
||||
break;
|
||||
case _OUTPUT_DNSSIM_CONN_INITIALIZED:
|
||||
case _OUTPUT_DNSSIM_CONN_CLOSE_REQUESTED:
|
||||
break;
|
||||
default:
|
||||
lfatal("unknown conn state: %d", conn->state);
|
||||
}
|
||||
if (conn->prevent_close) {
|
||||
lassert(conn->state <= _OUTPUT_DNSSIM_CONN_CLOSE_REQUESTED, "conn already closing");
|
||||
conn->state = _OUTPUT_DNSSIM_CONN_CLOSE_REQUESTED;
|
||||
return;
|
||||
}
|
||||
conn->state = _OUTPUT_DNSSIM_CONN_CLOSING;
|
||||
|
||||
if (conn->handshake_timer != NULL) {
|
||||
uv_timer_stop(conn->handshake_timer);
|
||||
uv_close((uv_handle_t*)conn->handshake_timer, _on_handshake_timer_closed);
|
||||
}
|
||||
if (conn->idle_timer != NULL) {
|
||||
conn->is_idle = false;
|
||||
uv_timer_stop(conn->idle_timer);
|
||||
uv_close((uv_handle_t*)conn->idle_timer, _on_idle_timer_closed);
|
||||
}
|
||||
|
||||
switch (_self->transport) {
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TCP:
|
||||
_output_dnssim_tcp_close(conn);
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TLS:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
_output_dnssim_tls_close(conn);
|
||||
#else
|
||||
lfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_HTTPS2:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
_output_dnssim_https2_close(conn);
|
||||
#else
|
||||
lfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
lfatal("unsupported transport");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close connection or run idle timer when there are no more outstanding queries. */
|
||||
void _output_dnssim_conn_idle(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn can't be nil");
|
||||
|
||||
if (conn->queued == NULL && conn->sent == NULL) {
|
||||
if (conn->idle_timer == NULL)
|
||||
_output_dnssim_conn_close(conn);
|
||||
else if (!conn->is_idle) {
|
||||
conn->is_idle = true;
|
||||
uv_timer_again(conn->idle_timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _send_pending_queries(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
_output_dnssim_query_tcp_t* qry;
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->client, "conn->client is nil");
|
||||
qry = (_output_dnssim_query_tcp_t*)conn->client->pending;
|
||||
|
||||
while (qry != NULL && conn->state == _OUTPUT_DNSSIM_CONN_ACTIVE) {
|
||||
_output_dnssim_query_tcp_t* next = (_output_dnssim_query_tcp_t*)qry->qry.next;
|
||||
if (qry->qry.state == _OUTPUT_DNSSIM_QUERY_PENDING_WRITE) {
|
||||
switch (qry->qry.transport) {
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TCP:
|
||||
_output_dnssim_tcp_write_query(conn, qry);
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TLS:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
_output_dnssim_tls_write_query(conn, qry);
|
||||
#else
|
||||
mlfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_HTTPS2:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
_output_dnssim_https2_write_query(conn, qry);
|
||||
#else
|
||||
mlfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
mlfatal("unsupported protocol");
|
||||
break;
|
||||
}
|
||||
}
|
||||
qry = next;
|
||||
}
|
||||
}
|
||||
|
||||
int _output_dnssim_handle_pending_queries(_output_dnssim_client_t* client)
|
||||
{
|
||||
int ret = 0;
|
||||
mlassert(client, "client is nil");
|
||||
|
||||
if (client->pending == NULL)
|
||||
return ret;
|
||||
|
||||
output_dnssim_t* self = client->dnssim;
|
||||
mlassert(self, "client must belong to dnssim");
|
||||
|
||||
/* Get active connection or find out whether new connection has to be opened. */
|
||||
bool is_connecting = false;
|
||||
_output_dnssim_connection_t* conn = client->conn;
|
||||
while (conn != NULL) {
|
||||
if (conn->state == _OUTPUT_DNSSIM_CONN_ACTIVE)
|
||||
break;
|
||||
else if (_conn_is_connecting(conn))
|
||||
is_connecting = true;
|
||||
conn = conn->next;
|
||||
}
|
||||
|
||||
if (conn != NULL) { /* Send data right away over active connection. */
|
||||
_send_pending_queries(conn);
|
||||
} else if (!is_connecting) { /* No active or connecting connection -> open a new one. */
|
||||
lfatal_oom(conn = calloc(1, sizeof(_output_dnssim_connection_t)));
|
||||
conn->state = _OUTPUT_DNSSIM_CONN_INITIALIZED;
|
||||
conn->client = client;
|
||||
conn->stats = self->stats_current;
|
||||
if (_self->transport == OUTPUT_DNSSIM_TRANSPORT_TLS) {
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
ret = _output_dnssim_tls_init(conn);
|
||||
if (ret < 0) {
|
||||
free(conn);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
lfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
} else if (_self->transport == OUTPUT_DNSSIM_TRANSPORT_HTTPS2) {
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
ret = _output_dnssim_https2_init(conn);
|
||||
if (ret < 0) {
|
||||
free(conn);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
lfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
}
|
||||
ret = _output_dnssim_tcp_connect(self, conn);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
_ll_append(client->conn, conn);
|
||||
} /* Otherwise, pending queries wil be sent after connected callback. */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _output_dnssim_conn_activate(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->client, "conn must be associated with a client");
|
||||
mlassert(conn->client->dnssim, "client must be associated with dnssim");
|
||||
|
||||
uv_timer_stop(conn->handshake_timer);
|
||||
|
||||
conn->state = _OUTPUT_DNSSIM_CONN_ACTIVE;
|
||||
conn->client->dnssim->stats_current->conn_active++;
|
||||
conn->read_state = _OUTPUT_DNSSIM_READ_STATE_DNSLEN;
|
||||
conn->dnsbuf_len = 2;
|
||||
conn->dnsbuf_pos = 0;
|
||||
conn->dnsbuf_free_after_use = false;
|
||||
|
||||
_send_pending_queries(conn);
|
||||
_output_dnssim_conn_idle(conn);
|
||||
}
|
||||
|
||||
int _process_dnsmsg(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn can't be nil");
|
||||
mlassert(conn->client, "conn must have client");
|
||||
mlassert(conn->client->dnssim, "client must have dnssim");
|
||||
|
||||
output_dnssim_t* self = conn->client->dnssim;
|
||||
|
||||
core_object_payload_t payload = CORE_OBJECT_PAYLOAD_INIT(NULL);
|
||||
core_object_dns_t dns_a = CORE_OBJECT_DNS_INIT(&payload);
|
||||
|
||||
payload.payload = (uint8_t*)conn->dnsbuf_data;
|
||||
payload.len = conn->dnsbuf_len;
|
||||
|
||||
dns_a.obj_prev = (core_object_t*)&payload;
|
||||
int ret = core_object_dns_parse_header(&dns_a);
|
||||
if (ret != 0) {
|
||||
lwarning("tcp response malformed");
|
||||
return _ERR_MALFORMED;
|
||||
}
|
||||
ldebug("tcp recv dnsmsg id: %04x", dns_a.id);
|
||||
|
||||
_output_dnssim_query_t* qry;
|
||||
|
||||
if (_self->transport == OUTPUT_DNSSIM_TRANSPORT_HTTPS2) {
|
||||
lassert(conn->http2, "conn must have http2 ctx");
|
||||
lassert(conn->http2->current_qry, "http2 has no current_qry");
|
||||
lassert(conn->http2->current_qry->qry.req, "current_qry has no req");
|
||||
lassert(conn->http2->current_qry->qry.req->dns_q, "req has no dns_q");
|
||||
|
||||
ret = _output_dnssim_answers_request(conn->http2->current_qry->qry.req, &dns_a);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
_output_dnssim_request_answered(conn->http2->current_qry->qry.req, &dns_a);
|
||||
break;
|
||||
case _ERR_MSGID:
|
||||
lwarning("https2 QID mismatch: request=0x%04x, response=0x%04x",
|
||||
conn->http2->current_qry->qry.req->dns_q->id, dns_a.id);
|
||||
break;
|
||||
case _ERR_QUESTION:
|
||||
default:
|
||||
lwarning("https2 response question mismatch");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
qry = conn->sent;
|
||||
while (qry != NULL) {
|
||||
if (qry->req->dns_q->id == dns_a.id) {
|
||||
ret = _output_dnssim_answers_request(qry->req, &dns_a);
|
||||
if (ret != 0) {
|
||||
lwarning("response question mismatch");
|
||||
} else {
|
||||
_output_dnssim_request_answered(qry->req, &dns_a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
qry = qry->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _parse_dnsbuf_data(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn can't be nil");
|
||||
mlassert(conn->dnsbuf_pos == conn->dnsbuf_len, "attempt to parse incomplete dnsbuf_data");
|
||||
int ret = 0;
|
||||
|
||||
switch (conn->read_state) {
|
||||
case _OUTPUT_DNSSIM_READ_STATE_DNSLEN: {
|
||||
uint16_t* p_dnslen = (uint16_t*)conn->dnsbuf_data;
|
||||
conn->dnsbuf_len = ntohs(*p_dnslen);
|
||||
if (conn->dnsbuf_len == 0) {
|
||||
mlwarning("invalid dnslen received: 0");
|
||||
conn->dnsbuf_len = 2;
|
||||
conn->read_state = _OUTPUT_DNSSIM_READ_STATE_DNSLEN;
|
||||
} else if (conn->dnsbuf_len < 12) {
|
||||
mldebug("invalid dnslen received: %d", conn->dnsbuf_len);
|
||||
ret = -1;
|
||||
} else {
|
||||
mldebug("dnslen: %d", conn->dnsbuf_len);
|
||||
conn->read_state = _OUTPUT_DNSSIM_READ_STATE_DNSMSG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case _OUTPUT_DNSSIM_READ_STATE_DNSMSG:
|
||||
ret = _process_dnsmsg(conn);
|
||||
if (ret) {
|
||||
conn->read_state = _OUTPUT_DNSSIM_READ_STATE_INVALID;
|
||||
} else {
|
||||
conn->dnsbuf_len = 2;
|
||||
conn->read_state = _OUTPUT_DNSSIM_READ_STATE_DNSLEN;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mlfatal("tcp invalid connection read_state");
|
||||
break;
|
||||
}
|
||||
|
||||
conn->dnsbuf_pos = 0;
|
||||
if (conn->dnsbuf_free_after_use) {
|
||||
conn->dnsbuf_free_after_use = false;
|
||||
free(conn->dnsbuf_data);
|
||||
}
|
||||
conn->dnsbuf_data = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int _read_dns_stream_chunk(_output_dnssim_connection_t* conn, size_t len, const char* data)
|
||||
{
|
||||
mlassert(conn, "conn can't be nil");
|
||||
mlassert(data, "data can't be nil");
|
||||
mlassert(len > 0, "no data to read");
|
||||
mlassert((conn->read_state == _OUTPUT_DNSSIM_READ_STATE_DNSLEN || conn->read_state == _OUTPUT_DNSSIM_READ_STATE_DNSMSG),
|
||||
"connection has invalid read_state");
|
||||
|
||||
int ret = 0;
|
||||
unsigned int nread;
|
||||
size_t expected = conn->dnsbuf_len - conn->dnsbuf_pos;
|
||||
mlassert(expected > 0, "no data expected");
|
||||
|
||||
if (conn->dnsbuf_free_after_use == false && expected > len) {
|
||||
/* Start of partial read. */
|
||||
mlassert(conn->dnsbuf_pos == 0, "conn->dnsbuf_pos must be 0 at start of partial read");
|
||||
mlassert(conn->dnsbuf_len > 0, "conn->dnsbuf_len must be set at start of partial read");
|
||||
mlfatal_oom(conn->dnsbuf_data = malloc(conn->dnsbuf_len * sizeof(char)));
|
||||
conn->dnsbuf_free_after_use = true;
|
||||
}
|
||||
|
||||
if (conn->dnsbuf_free_after_use) { /* Partial read is in progress. */
|
||||
char* dest = conn->dnsbuf_data + conn->dnsbuf_pos;
|
||||
if (expected < len)
|
||||
len = expected;
|
||||
memcpy(dest, data, len);
|
||||
conn->dnsbuf_pos += len;
|
||||
nread = len;
|
||||
} else { /* Complete and clean read. */
|
||||
mlassert(expected <= len, "not enough data to perform complete read");
|
||||
conn->dnsbuf_data = (char*)data;
|
||||
conn->dnsbuf_pos = conn->dnsbuf_len;
|
||||
nread = expected;
|
||||
}
|
||||
|
||||
/* If entire dnslen/dnsmsg was read, attempt to parse it. */
|
||||
if (conn->dnsbuf_len == conn->dnsbuf_pos) {
|
||||
ret = _parse_dnsbuf_data(conn);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
void _output_dnssim_read_dns_stream(_output_dnssim_connection_t* conn, size_t len, const char* data)
|
||||
{
|
||||
int pos = 0;
|
||||
int chunk = 0;
|
||||
while (pos < len) {
|
||||
chunk = _read_dns_stream_chunk(conn, len - pos, data + pos);
|
||||
if (chunk < 0) {
|
||||
mlwarning("lost orientation in DNS stream, closing");
|
||||
_output_dnssim_conn_close(conn);
|
||||
break;
|
||||
} else {
|
||||
pos += chunk;
|
||||
}
|
||||
}
|
||||
mlassert((pos == len) || (chunk < 0), "dns stream read invalid, pos != len");
|
||||
}
|
||||
|
||||
void _output_dnssim_read_dnsmsg(_output_dnssim_connection_t* conn, size_t len, const char* data)
|
||||
{
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(len > 0, "len is zero");
|
||||
mlassert(data, "no data");
|
||||
mlassert(conn->dnsbuf_pos == 0, "dnsbuf not empty");
|
||||
mlassert(conn->dnsbuf_free_after_use == false, "dnsbuf read in progress");
|
||||
|
||||
/* Read dnsmsg of given length from input data. */
|
||||
conn->dnsbuf_len = len;
|
||||
conn->read_state = _OUTPUT_DNSSIM_READ_STATE_DNSMSG;
|
||||
int nread = _read_dns_stream_chunk(conn, len, data);
|
||||
|
||||
if (nread != len) {
|
||||
mlwarning("failed to read received dnsmsg");
|
||||
if (conn->dnsbuf_free_after_use)
|
||||
free(conn->dnsbuf_data);
|
||||
}
|
||||
|
||||
/* Clean state afterwards. */
|
||||
conn->read_state = _OUTPUT_DNSSIM_READ_STATE_DNSLEN;
|
||||
conn->dnsbuf_len = 2;
|
||||
conn->dnsbuf_pos = 0;
|
||||
conn->dnsbuf_free_after_use = false;
|
||||
}
|
|
@ -1,592 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020, CZ.NIC, z.s.p.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "output/dnssim.h"
|
||||
#include "output/dnssim/internal.h"
|
||||
#include "output/dnssim/ll.h"
|
||||
#include "core/assert.h"
|
||||
#include "lib/base64url.h"
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <string.h>
|
||||
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
|
||||
#define OUTPUT_DNSSIM_MAKE_NV(NAME, VALUE, VALUELEN) \
|
||||
{ \
|
||||
(uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, VALUELEN, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
#define OUTPUT_DNSSIM_MAKE_NV2(NAME, VALUE) \
|
||||
{ \
|
||||
(uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
#define OUTPUT_DNSSIM_HTTP_GET_TEMPLATE "?dns="
|
||||
#define OUTPUT_DNSSIM_HTTP_GET_TEMPLATE_LEN (sizeof(OUTPUT_DNSSIM_HTTP_GET_TEMPLATE) - 1)
|
||||
#define OUTPUT_DNSSIM_HTTP2_INITIAL_MAX_CONCURRENT_STREAMS 100
|
||||
#define OUTPUT_DNSSIM_HTTP2_DEFAULT_MAX_CONCURRENT_STREAMS 0xffffffffu
|
||||
|
||||
static core_log_t _log = LOG_T_INIT("output.dnssim");
|
||||
|
||||
static ssize_t _http2_send(nghttp2_session* session, const uint8_t* data, size_t length, int flags, void* user_data)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)user_data;
|
||||
mlassert(conn, "conn can't be null");
|
||||
mlassert(conn->tls, "conn must have tls ctx");
|
||||
mlassert(conn->tls->session, "conn must have tls session");
|
||||
|
||||
mldebug("http2 (%p): sending data, len=%ld", session, length);
|
||||
|
||||
ssize_t len = 0;
|
||||
if ((len = gnutls_record_send(conn->tls->session, data, length)) < 0) {
|
||||
mlwarning("gnutls_record_send failed: %s", gnutls_strerror(len));
|
||||
len = NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t _http2_on_data_provider_read(nghttp2_session* session, int32_t stream_id, uint8_t* buf, size_t length, uint32_t* data_flags, nghttp2_data_source* source, void* user_data)
|
||||
{
|
||||
_output_dnssim_https2_data_provider_t* buffer = source->ptr;
|
||||
mlassert(buffer, "no data provider");
|
||||
mlassert(buffer->len <= MAX_DNSMSG_SIZE, "invalid dnsmsg size: %zu B", buffer->len);
|
||||
|
||||
ssize_t sent = (length < buffer->len) ? length : buffer->len;
|
||||
mlassert(sent >= 0, "negative length of bytes to send");
|
||||
|
||||
memcpy(buf, buffer->buf, sent);
|
||||
buffer->buf += sent;
|
||||
buffer->len -= sent;
|
||||
if (buffer->len == 0)
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
static _output_dnssim_query_tcp_t* _http2_get_stream_qry(_output_dnssim_connection_t* conn, int32_t stream_id)
|
||||
{
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(stream_id >= 0, "invalid stream_id");
|
||||
|
||||
_output_dnssim_query_tcp_t* qry = (_output_dnssim_query_tcp_t*)conn->sent;
|
||||
while (qry != NULL && qry->stream_id != stream_id) {
|
||||
qry = (_output_dnssim_query_tcp_t*)qry->qry.next;
|
||||
}
|
||||
|
||||
return qry;
|
||||
}
|
||||
|
||||
static int _http2_on_header(nghttp2_session* session, const nghttp2_frame* frame, const uint8_t* name, size_t namelen, const uint8_t* value, size_t valuelen, uint8_t flags, void* user_data)
|
||||
{
|
||||
if (frame->hd.type == NGHTTP2_HEADERS && frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
|
||||
if (namelen == 7 && strncmp((char*)name, ":status", 7) == 0) {
|
||||
if (valuelen != 3 || (value[0] != '1' && value[0] != '2')) {
|
||||
/* When reponse code isn't 1xx or 2xx, close the query.
|
||||
* This will result in request timeout, which currently seems
|
||||
* slightly better than mocking SERVFAIL for statistics. */
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)user_data;
|
||||
mlassert(conn, "conn is nil");
|
||||
_output_dnssim_query_tcp_t* qry = _http2_get_stream_qry(conn, frame->hd.stream_id);
|
||||
|
||||
if (qry != NULL) {
|
||||
_output_dnssim_close_query_https2(qry);
|
||||
mlinfo("http response %s, closing query", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _http2_on_data_recv(nghttp2_session* session, uint8_t flags, int32_t stream_id, const uint8_t* data, size_t len, void* user_data)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)user_data;
|
||||
mlassert(conn, "conn is nil");
|
||||
|
||||
_output_dnssim_query_tcp_t* qry = _http2_get_stream_qry(conn, stream_id);
|
||||
|
||||
mldebug("http2: data chunk recv, session=%p, len=%d", session, len);
|
||||
|
||||
if (qry) {
|
||||
if (qry->recv_buf_len == 0) {
|
||||
if (len > MAX_DNSMSG_SIZE) {
|
||||
mlwarning("http response exceeded maximum size of dns message");
|
||||
return -1;
|
||||
}
|
||||
mlfatal_oom(qry->recv_buf = malloc(len));
|
||||
memcpy(qry->recv_buf, data, len);
|
||||
qry->recv_buf_len = len;
|
||||
} else {
|
||||
size_t total_len = qry->recv_buf_len + len;
|
||||
if (total_len > MAX_DNSMSG_SIZE) {
|
||||
mlwarning("http response exceeded maximum size of dns message");
|
||||
return -1;
|
||||
}
|
||||
mlfatal_oom(qry->recv_buf = realloc(qry->recv_buf, total_len));
|
||||
memcpy(qry->recv_buf + qry->recv_buf_len, data, len);
|
||||
qry->recv_buf_len = total_len;
|
||||
}
|
||||
} else {
|
||||
mldebug("no query associated with this stream id, ignoring");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _http2_check_max_streams(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn can't be null");
|
||||
mlassert(conn->http2, "conn must have http2 ctx");
|
||||
|
||||
switch (conn->state) {
|
||||
case _OUTPUT_DNSSIM_CONN_ACTIVE:
|
||||
if (conn->http2->open_streams >= conn->http2->max_concurrent_streams) {
|
||||
mlinfo("http2 (%p): reached maximum number of concurrent streams (%ld)",
|
||||
conn->http2->session, conn->http2->max_concurrent_streams);
|
||||
conn->state = _OUTPUT_DNSSIM_CONN_CONGESTED;
|
||||
}
|
||||
break;
|
||||
case _OUTPUT_DNSSIM_CONN_CONGESTED:
|
||||
if (conn->http2->open_streams < conn->http2->max_concurrent_streams)
|
||||
conn->state = _OUTPUT_DNSSIM_CONN_ACTIVE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int _http2_on_stream_close(nghttp2_session* session, int32_t stream_id, uint32_t error_code, void* user_data)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)user_data;
|
||||
mlassert(conn, "conn can't be null");
|
||||
mlassert(conn->http2, "conn must have http2 ctx");
|
||||
mlassert(conn->http2->open_streams > 0, "conn has no open streams");
|
||||
|
||||
conn->http2->open_streams--;
|
||||
_http2_check_max_streams(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _http2_on_frame_recv(nghttp2_session* session, const nghttp2_frame* frame, void* user_data)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)user_data;
|
||||
mlassert(conn, "conn can't be null");
|
||||
mlassert(conn->tls, "conn must have tls ctx");
|
||||
mlassert(conn->tls->session, "conn must have tls session");
|
||||
mlassert(conn->http2, "conn must have http2 ctx");
|
||||
|
||||
switch (frame->hd.type) {
|
||||
case NGHTTP2_DATA:
|
||||
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
|
||||
mldebug("http2 (%p): final DATA frame recv", session);
|
||||
_output_dnssim_query_tcp_t* qry = _http2_get_stream_qry(conn, frame->hd.stream_id);
|
||||
|
||||
if (qry != NULL) {
|
||||
conn->http2->current_qry = qry;
|
||||
_output_dnssim_read_dnsmsg(conn, qry->recv_buf_len, (char*)qry->recv_buf);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NGHTTP2_SETTINGS:
|
||||
if (!conn->http2->remote_settings_received) {
|
||||
/* On the first SETTINGS frame, set concurrent streams to unlimited, same as nghttp2. */
|
||||
conn->http2->remote_settings_received = true;
|
||||
conn->http2->max_concurrent_streams = OUTPUT_DNSSIM_HTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
|
||||
_http2_check_max_streams(conn);
|
||||
}
|
||||
nghttp2_settings* settings = (nghttp2_settings*)frame;
|
||||
int i;
|
||||
for (i = 0; i < settings->niv; i++) {
|
||||
switch (settings->iv[i].settings_id) {
|
||||
case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
|
||||
conn->http2->max_concurrent_streams = settings->iv[i].value;
|
||||
_http2_check_max_streams(conn);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _output_dnssim_https2_init(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->tls == NULL, "conn already has tls context");
|
||||
mlassert(conn->http2 == NULL, "conn already has http2 context");
|
||||
mlassert(conn->client, "conn must be associated with a client");
|
||||
mlassert(conn->client->dnssim, "client must have dnssim");
|
||||
|
||||
int ret = -1;
|
||||
nghttp2_session_callbacks* callbacks;
|
||||
nghttp2_option* option;
|
||||
output_dnssim_t* self = conn->client->dnssim;
|
||||
|
||||
/* Initialize TLS session. */
|
||||
ret = _output_dnssim_tls_init(conn);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Configure ALPN to negotiate HTTP/2. */
|
||||
const gnutls_datum_t protos[] = {
|
||||
{ (unsigned char*)"h2", 2 }
|
||||
};
|
||||
ret = gnutls_alpn_set_protocols(conn->tls->session, protos, 1, 0);
|
||||
if (ret < 0) {
|
||||
lwarning("failed to set ALPN protocol: %s", gnutls_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
lfatal_oom(conn->http2 = calloc(1, sizeof(_output_dnssim_http2_ctx_t)));
|
||||
conn->http2->max_concurrent_streams = OUTPUT_DNSSIM_HTTP2_INITIAL_MAX_CONCURRENT_STREAMS;
|
||||
|
||||
/* Set up HTTP/2 callbacks and client. */
|
||||
lassert(nghttp2_session_callbacks_new(&callbacks) == 0, "out of memory");
|
||||
nghttp2_session_callbacks_set_send_callback(callbacks, _http2_send);
|
||||
nghttp2_session_callbacks_set_on_header_callback(callbacks, _http2_on_header);
|
||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(callbacks, _http2_on_data_recv);
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, _http2_on_frame_recv);
|
||||
nghttp2_session_callbacks_set_on_stream_close_callback(callbacks, _http2_on_stream_close);
|
||||
|
||||
lassert(nghttp2_option_new(&option) == 0, "out of memory");
|
||||
nghttp2_option_set_peer_max_concurrent_streams(option, conn->http2->max_concurrent_streams);
|
||||
|
||||
ret = nghttp2_session_client_new2(&conn->http2->session, callbacks, conn, option);
|
||||
|
||||
nghttp2_session_callbacks_del(callbacks);
|
||||
nghttp2_option_del(option);
|
||||
|
||||
if (ret < 0) {
|
||||
free(conn->http2);
|
||||
conn->http2 = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _output_dnssim_https2_setup(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->tls, "conn must have tls ctx");
|
||||
mlassert(conn->tls->session, "conn must have tls session");
|
||||
mlassert(conn->http2, "conn must have http2 ctx");
|
||||
mlassert(conn->http2->session, "conn must have http2 session");
|
||||
|
||||
int ret = -1;
|
||||
|
||||
/* Check "h2" protocol was negotiated with ALPN. */
|
||||
gnutls_datum_t proto;
|
||||
ret = gnutls_alpn_get_selected_protocol(conn->tls->session, &proto);
|
||||
if (ret < 0) {
|
||||
mlwarning("http2: failed to get negotiated protocol: %s", gnutls_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
if (proto.size != 2 || memcmp("h2", proto.data, 2) != 0) {
|
||||
mlwarning("http2: protocol is not negotiated");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Submit SETTIGNS frame. */
|
||||
static const nghttp2_settings_entry iv[] = {
|
||||
{ NGHTTP2_SETTINGS_MAX_FRAME_SIZE, MAX_DNSMSG_SIZE },
|
||||
{ NGHTTP2_SETTINGS_ENABLE_PUSH, 0 }, /* Only we can initiate streams. */
|
||||
};
|
||||
ret = nghttp2_submit_settings(conn->http2->session, NGHTTP2_FLAG_NONE, iv, sizeof(iv) / sizeof(*iv));
|
||||
if (ret < 0) {
|
||||
mlwarning("http2: failed to submit SETTINGS: %s", nghttp2_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _output_dnssim_https2_process_input_data(_output_dnssim_connection_t* conn, size_t len, const char* data)
|
||||
{
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->http2, "conn must have http2 ctx");
|
||||
mlassert(conn->http2->session, "conn must have http2 session");
|
||||
|
||||
/* Process incoming frames. */
|
||||
ssize_t ret = 0;
|
||||
conn->prevent_close = true;
|
||||
ret = nghttp2_session_mem_recv(conn->http2->session, (uint8_t*)data, len);
|
||||
conn->prevent_close = false;
|
||||
if (ret < 0) {
|
||||
mlwarning("failed nghttp2_session_mem_recv: %s", nghttp2_strerror(ret));
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
} else if (conn->state == _OUTPUT_DNSSIM_CONN_CLOSE_REQUESTED) {
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
mlassert(ret == len, "nghttp2_session_mem_recv didn't process all data");
|
||||
|
||||
/* Send any frames the read might have triggered. */
|
||||
ret = nghttp2_session_send(conn->http2->session);
|
||||
if (ret < 0) {
|
||||
mlwarning("failed nghttp2_session_send: %s", nghttp2_strerror(ret));
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int _output_dnssim_create_query_https2(output_dnssim_t* self, _output_dnssim_request_t* req)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(req, "req is nil");
|
||||
lassert(req->client, "request must have a client associated with it");
|
||||
|
||||
_output_dnssim_query_tcp_t* qry;
|
||||
|
||||
lfatal_oom(qry = calloc(1, sizeof(_output_dnssim_query_tcp_t)));
|
||||
|
||||
qry->qry.transport = OUTPUT_DNSSIM_TRANSPORT_HTTPS2;
|
||||
qry->qry.req = req;
|
||||
qry->qry.state = _OUTPUT_DNSSIM_QUERY_PENDING_WRITE;
|
||||
qry->stream_id = -1;
|
||||
req->qry = &qry->qry; // TODO change when adding support for multiple Qs for req
|
||||
_ll_append(req->client->pending, &qry->qry);
|
||||
|
||||
return _output_dnssim_handle_pending_queries(req->client);
|
||||
}
|
||||
|
||||
void _output_dnssim_close_query_https2(_output_dnssim_query_tcp_t* qry)
|
||||
{
|
||||
mlassert(qry, "qry can't be null");
|
||||
mlassert(qry->qry.req, "query must be part of a request");
|
||||
_output_dnssim_request_t* req = qry->qry.req;
|
||||
mlassert(req->client, "request must belong to a client");
|
||||
|
||||
_ll_try_remove(req->client->pending, &qry->qry);
|
||||
if (qry->conn) {
|
||||
_output_dnssim_connection_t* conn = qry->conn;
|
||||
_ll_try_remove(conn->sent, &qry->qry);
|
||||
qry->conn = NULL;
|
||||
_output_dnssim_conn_idle(conn);
|
||||
}
|
||||
|
||||
if (qry->recv_buf != NULL)
|
||||
free(qry->recv_buf);
|
||||
|
||||
_ll_remove(req->qry, &qry->qry);
|
||||
free(qry);
|
||||
}
|
||||
|
||||
void _output_dnssim_https2_close(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn can't be nil");
|
||||
mlassert(conn->http2, "conn must have http2 ctx");
|
||||
|
||||
nghttp2_session_del(conn->http2->session);
|
||||
_output_dnssim_tls_close(conn);
|
||||
}
|
||||
|
||||
static int _http2_send_query_get(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry)
|
||||
{
|
||||
mlassert(conn, "conn can't be null");
|
||||
mlassert(qry, "qry can't be null");
|
||||
mlassert(qry->qry.req, "req can't be null");
|
||||
mlassert(qry->qry.req->payload, "payload can't be null");
|
||||
mlassert(qry->qry.req->payload->len <= MAX_DNSMSG_SIZE, "payload too big");
|
||||
mlassert(conn->client, "conn must be associated with client");
|
||||
mlassert(conn->client->dnssim, "client must have dnssim");
|
||||
|
||||
output_dnssim_t* self = conn->client->dnssim;
|
||||
core_object_payload_t* content = qry->qry.req->payload;
|
||||
|
||||
const size_t uri_path_len = strlen(_self->h2_uri_path);
|
||||
const size_t path_len = uri_path_len
|
||||
+ OUTPUT_DNSSIM_HTTP_GET_TEMPLATE_LEN
|
||||
+ (content->len * 4) / 3 + 3 /* upper limit of base64 encoding */
|
||||
+ 1; /* terminating null byte */
|
||||
if (path_len >= _MAX_URI_LEN) {
|
||||
self->discarded++;
|
||||
linfo("http2: uri path with query too long, query discarded");
|
||||
return 0;
|
||||
}
|
||||
char path[path_len];
|
||||
memcpy(path, _self->h2_uri_path, uri_path_len);
|
||||
memcpy(&path[uri_path_len], OUTPUT_DNSSIM_HTTP_GET_TEMPLATE, OUTPUT_DNSSIM_HTTP_GET_TEMPLATE_LEN);
|
||||
|
||||
int32_t ret = base64url_encode(content->payload, content->len,
|
||||
(uint8_t*)&path[uri_path_len + OUTPUT_DNSSIM_HTTP_GET_TEMPLATE_LEN],
|
||||
sizeof(path) - uri_path_len - OUTPUT_DNSSIM_HTTP_GET_TEMPLATE_LEN - 1);
|
||||
if (ret < 0) {
|
||||
self->discarded++;
|
||||
linfo("http2: base64url encode of query failed, query discarded");
|
||||
return 0;
|
||||
}
|
||||
|
||||
nghttp2_nv hdrs[] = {
|
||||
OUTPUT_DNSSIM_MAKE_NV2(":method", "GET"),
|
||||
OUTPUT_DNSSIM_MAKE_NV2(":scheme", "https"),
|
||||
OUTPUT_DNSSIM_MAKE_NV(":authority", _self->h2_uri_authority, strlen(_self->h2_uri_authority)),
|
||||
OUTPUT_DNSSIM_MAKE_NV(":path", path, uri_path_len + sizeof(OUTPUT_DNSSIM_HTTP_GET_TEMPLATE) - 1 + ret),
|
||||
OUTPUT_DNSSIM_MAKE_NV2("accept", "application/dns-message"),
|
||||
};
|
||||
|
||||
qry->stream_id = nghttp2_submit_request(conn->http2->session, NULL, hdrs, sizeof(hdrs) / sizeof(nghttp2_nv), NULL, NULL);
|
||||
|
||||
if (qry->stream_id < 0) {
|
||||
mldebug("http2 (%p): failed to submit request: %s", conn->http2->session, nghttp2_strerror(qry->stream_id));
|
||||
return -1;
|
||||
}
|
||||
mldebug("http2 (%p): GET %s", conn->http2->session, path);
|
||||
conn->http2->open_streams++;
|
||||
_http2_check_max_streams(conn);
|
||||
|
||||
ret = nghttp2_session_send(conn->http2->session);
|
||||
if (ret < 0) {
|
||||
mldebug("http2 (%p): failed session send: %s", conn->http2->session, nghttp2_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _http2_send_query_post(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry)
|
||||
{
|
||||
mlassert(conn, "conn can't be null");
|
||||
mlassert(qry, "qry can't be null");
|
||||
mlassert(qry->qry.req, "req can't be null");
|
||||
mlassert(qry->qry.req->payload, "payload can't be null");
|
||||
mlassert(qry->qry.req->payload->len <= MAX_DNSMSG_SIZE, "payload too big");
|
||||
mlassert(conn->client, "conn must be associated with client");
|
||||
mlassert(conn->client->dnssim, "client must have dnssim");
|
||||
|
||||
output_dnssim_t* self = conn->client->dnssim;
|
||||
|
||||
core_object_payload_t* content = qry->qry.req->payload;
|
||||
|
||||
int window_size = nghttp2_session_get_remote_window_size(conn->http2->session);
|
||||
if (content->len > window_size) {
|
||||
mldebug("http2 (%p): insufficient remote window size, deferring", conn->http2->session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char content_length[6]; /* max dnslen "65535" */
|
||||
int content_length_len = snprintf(content_length, 6, "%zd", content->len);
|
||||
|
||||
nghttp2_nv hdrs[] = {
|
||||
OUTPUT_DNSSIM_MAKE_NV2(":method", "POST"),
|
||||
OUTPUT_DNSSIM_MAKE_NV2(":scheme", "https"),
|
||||
OUTPUT_DNSSIM_MAKE_NV(":authority", _self->h2_uri_authority, strlen(_self->h2_uri_authority)),
|
||||
OUTPUT_DNSSIM_MAKE_NV(":path", _self->h2_uri_path, strlen(_self->h2_uri_path)),
|
||||
OUTPUT_DNSSIM_MAKE_NV2("accept", "application/dns-message"),
|
||||
OUTPUT_DNSSIM_MAKE_NV2("content-type", "application/dns-message"),
|
||||
OUTPUT_DNSSIM_MAKE_NV("content-length", content_length, content_length_len)
|
||||
};
|
||||
|
||||
_output_dnssim_https2_data_provider_t data = {
|
||||
.buf = content->payload,
|
||||
.len = content->len
|
||||
};
|
||||
|
||||
nghttp2_data_provider data_provider = {
|
||||
.source.ptr = &data,
|
||||
.read_callback = _http2_on_data_provider_read
|
||||
};
|
||||
|
||||
qry->stream_id = nghttp2_submit_request(conn->http2->session, NULL, hdrs, sizeof(hdrs) / sizeof(nghttp2_nv), &data_provider, NULL);
|
||||
|
||||
if (qry->stream_id < 0) {
|
||||
mldebug("http2 (%p): failed to submit request: %s", conn->http2->session, nghttp2_strerror(qry->stream_id));
|
||||
return -1;
|
||||
}
|
||||
mldebug("http2 (%p): POST payload len=%ld", conn->http2->session, content->len);
|
||||
conn->http2->open_streams++;
|
||||
_http2_check_max_streams(conn);
|
||||
|
||||
window_size = nghttp2_session_get_stream_remote_window_size(conn->http2->session, qry->stream_id);
|
||||
mlassert(content->len <= window_size,
|
||||
"unsupported: http2 stream window size (%ld B) is smaller than dns payload (%ld B)",
|
||||
window_size, content->len);
|
||||
|
||||
int ret = nghttp2_session_send(conn->http2->session);
|
||||
if (ret < 0) {
|
||||
mldebug("http2 (%p): failed session send: %s", conn->http2->session, nghttp2_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _output_dnssim_https2_write_query(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry)
|
||||
{
|
||||
mlassert(qry, "qry can't be null");
|
||||
mlassert(qry->qry.state == _OUTPUT_DNSSIM_QUERY_PENDING_WRITE, "qry must be pending write");
|
||||
mlassert(conn, "conn can't be null");
|
||||
mlassert(conn->state == _OUTPUT_DNSSIM_CONN_ACTIVE, "connection state != ACTIVE");
|
||||
mlassert(conn->http2, "conn must have http2 ctx");
|
||||
mlassert(conn->http2->session, "conn must have http2 session");
|
||||
mlassert(conn->client, "conn must be associated with client");
|
||||
mlassert(conn->client->pending, "conn has no pending queries");
|
||||
mlassert(conn->client->dnssim, "client must have dnssim");
|
||||
|
||||
int ret = 0;
|
||||
output_dnssim_t* self = conn->client->dnssim;
|
||||
|
||||
if (!nghttp2_session_check_request_allowed(conn->http2->session)) {
|
||||
mldebug("http2 (%p): request not allowed", conn->http2->session);
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_self->h2_method) {
|
||||
case OUTPUT_DNSSIM_H2_POST:
|
||||
ret = _http2_send_query_post(conn, qry);
|
||||
break;
|
||||
case OUTPUT_DNSSIM_H2_GET:
|
||||
ret = _http2_send_query_get(conn, qry);
|
||||
break;
|
||||
default:
|
||||
lfatal("http2: unsupported method");
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
qry->conn = conn;
|
||||
_ll_remove(conn->client->pending, &qry->qry);
|
||||
_ll_append(conn->sent, &qry->qry);
|
||||
|
||||
/* Stop idle timer, since there are queries to answer now. */
|
||||
if (conn->idle_timer != NULL) {
|
||||
conn->is_idle = false;
|
||||
uv_timer_stop(conn->idle_timer);
|
||||
}
|
||||
|
||||
qry->qry.state = _OUTPUT_DNSSIM_QUERY_SENT;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,343 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020, CZ.NIC, z.s.p.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __dnsjit_output_dnssim_internal_h
|
||||
#define __dnsjit_output_dnssim_internal_h
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include <uv.h>
|
||||
#include "core/object/dns.h"
|
||||
#include "core/object/payload.h"
|
||||
|
||||
#define DNSSIM_MIN_GNUTLS_VERSION 0x030603
|
||||
#define DNSSIM_MIN_GNUTLS_ERRORMSG "dnssim tls/https2 transport requires GnuTLS >= 3.6.3"
|
||||
|
||||
#define _self ((_output_dnssim_t*)self)
|
||||
#define _ERR_MALFORMED -2
|
||||
#define _ERR_MSGID -3
|
||||
#define _ERR_TC -4
|
||||
#define _ERR_QUESTION -5
|
||||
|
||||
#define _MAX_URI_LEN 65536
|
||||
#define MAX_DNSMSG_SIZE 65535
|
||||
#define WIRE_BUF_SIZE (MAX_DNSMSG_SIZE + 2 + 16384) /** max tcplen + 2b tcplen + 16kb tls record */
|
||||
|
||||
typedef struct _output_dnssim_request _output_dnssim_request_t;
|
||||
typedef struct _output_dnssim_connection _output_dnssim_connection_t;
|
||||
typedef struct _output_dnssim_client _output_dnssim_client_t;
|
||||
|
||||
/*
|
||||
* Query-related structures.
|
||||
*/
|
||||
|
||||
typedef struct _output_dnssim_query _output_dnssim_query_t;
|
||||
struct _output_dnssim_query {
|
||||
/*
|
||||
* Next query in the list.
|
||||
*
|
||||
* Currently, next is used for TCP clients/connection, which makes it
|
||||
* impossible to use for tracking multiple queries of a single request.
|
||||
*
|
||||
* TODO: refactor the linked lists to allow query to be part of multiple lists
|
||||
*/
|
||||
_output_dnssim_query_t* next;
|
||||
|
||||
output_dnssim_transport_t transport;
|
||||
_output_dnssim_request_t* req;
|
||||
|
||||
/* Query state, currently used only for TCP. */
|
||||
enum {
|
||||
_OUTPUT_DNSSIM_QUERY_PENDING_WRITE,
|
||||
_OUTPUT_DNSSIM_QUERY_PENDING_WRITE_CB,
|
||||
_OUTPUT_DNSSIM_QUERY_PENDING_CLOSE,
|
||||
_OUTPUT_DNSSIM_QUERY_WRITE_FAILED,
|
||||
_OUTPUT_DNSSIM_QUERY_SENT,
|
||||
_OUTPUT_DNSSIM_QUERY_ORPHANED
|
||||
} state;
|
||||
};
|
||||
|
||||
typedef struct _output_dnssim_query_udp _output_dnssim_query_udp_t;
|
||||
struct _output_dnssim_query_udp {
|
||||
_output_dnssim_query_t qry;
|
||||
|
||||
uv_udp_t* handle;
|
||||
uv_buf_t buf;
|
||||
};
|
||||
|
||||
typedef struct _output_dnssim_query_tcp _output_dnssim_query_tcp_t;
|
||||
struct _output_dnssim_query_tcp {
|
||||
_output_dnssim_query_t qry;
|
||||
|
||||
/* Connection this query is assigned to. */
|
||||
_output_dnssim_connection_t* conn;
|
||||
|
||||
uv_write_t write_req;
|
||||
|
||||
/* Send buffers for libuv; 0 is for dnslen, 1 is for dnsmsg. */
|
||||
uv_buf_t bufs[2];
|
||||
|
||||
/* HTTP/2 stream id that was used to send this query. */
|
||||
int32_t stream_id;
|
||||
|
||||
/* HTTP/2 expected content length. */
|
||||
int32_t content_len;
|
||||
|
||||
/* Receive buffer (currently used only by HTTP/2). */
|
||||
uint8_t* recv_buf;
|
||||
ssize_t recv_buf_len;
|
||||
};
|
||||
|
||||
struct _output_dnssim_request {
|
||||
/* List of queries associated with this request. */
|
||||
_output_dnssim_query_t* qry;
|
||||
|
||||
/* Client this request belongs to. */
|
||||
_output_dnssim_client_t* client;
|
||||
|
||||
/* The DNS question to be resolved. */
|
||||
core_object_payload_t* payload;
|
||||
core_object_dns_t* dns_q;
|
||||
const uint8_t* question;
|
||||
ssize_t question_len;
|
||||
|
||||
/* Timestamps for latency calculation. */
|
||||
uint64_t created_at;
|
||||
uint64_t ended_at;
|
||||
|
||||
/* Timer for tracking timeout of the request. */
|
||||
uv_timer_t* timer;
|
||||
|
||||
/* The output component of this request. */
|
||||
output_dnssim_t* dnssim;
|
||||
|
||||
/* State of the request. */
|
||||
enum {
|
||||
_OUTPUT_DNSSIM_REQ_ONGOING,
|
||||
_OUTPUT_DNSSIM_REQ_CLOSING
|
||||
} state;
|
||||
|
||||
/* Statistics interval in which this request is tracked. */
|
||||
output_dnssim_stats_t* stats;
|
||||
};
|
||||
|
||||
/*
|
||||
* Connection-related structures.
|
||||
*/
|
||||
|
||||
/* Read-state of connection's data stream. */
|
||||
typedef enum _output_dnssim_read_state {
|
||||
_OUTPUT_DNSSIM_READ_STATE_CLEAN,
|
||||
_OUTPUT_DNSSIM_READ_STATE_DNSLEN, /* Expecting bytes of dnslen. */
|
||||
_OUTPUT_DNSSIM_READ_STATE_DNSMSG, /* Expecting bytes of dnsmsg. */
|
||||
_OUTPUT_DNSSIM_READ_STATE_INVALID
|
||||
} _output_dnssim_read_state_t;
|
||||
|
||||
/* TLS-related data for a single connection. */
|
||||
typedef struct _output_dnssim_tls_ctx {
|
||||
gnutls_session_t session;
|
||||
uint8_t* buf;
|
||||
ssize_t buf_len;
|
||||
ssize_t buf_pos;
|
||||
size_t write_queue_size;
|
||||
} _output_dnssim_tls_ctx_t;
|
||||
|
||||
/* HTTP2 context for a single connection. */
|
||||
typedef struct _output_dnssim_http2_ctx {
|
||||
nghttp2_session* session;
|
||||
|
||||
/* Query to which the dnsbuf currently being processed belongs to. */
|
||||
_output_dnssim_query_tcp_t* current_qry;
|
||||
|
||||
/* Maximum number of concurrent and currently open streams. */
|
||||
uint32_t max_concurrent_streams;
|
||||
uint32_t open_streams;
|
||||
|
||||
/* Flag indicating whether we received the peer's initial SETTINGS frame. */
|
||||
bool remote_settings_received;
|
||||
} _output_dnssim_http2_ctx_t;
|
||||
|
||||
struct _output_dnssim_connection {
|
||||
_output_dnssim_connection_t* next;
|
||||
|
||||
uv_tcp_t* handle;
|
||||
|
||||
/* Timeout timer for establishing the connection. */
|
||||
uv_timer_t* handshake_timer;
|
||||
|
||||
/* Idle timer for connection reuse. rfc7766#section-6.2.3 */
|
||||
uv_timer_t* idle_timer;
|
||||
bool is_idle;
|
||||
|
||||
/* List of queries that have been queued (pending write callback). */
|
||||
_output_dnssim_query_t* queued;
|
||||
|
||||
/* List of queries that have been sent over this connection. */
|
||||
_output_dnssim_query_t* sent;
|
||||
|
||||
/* Client this connection belongs to. */
|
||||
_output_dnssim_client_t* client;
|
||||
|
||||
/* State of the connection.
|
||||
* Numeric ordering of constants is significant and follows the typical connection lifecycle.
|
||||
* Ensure new states are added to a proper place. */
|
||||
enum {
|
||||
_OUTPUT_DNSSIM_CONN_INITIALIZED = 0,
|
||||
_OUTPUT_DNSSIM_CONN_TCP_HANDSHAKE = 10,
|
||||
_OUTPUT_DNSSIM_CONN_TLS_HANDSHAKE = 20,
|
||||
_OUTPUT_DNSSIM_CONN_ACTIVE = 30,
|
||||
_OUTPUT_DNSSIM_CONN_CONGESTED = 35,
|
||||
_OUTPUT_DNSSIM_CONN_CLOSE_REQUESTED = 38,
|
||||
_OUTPUT_DNSSIM_CONN_CLOSING = 40,
|
||||
_OUTPUT_DNSSIM_CONN_CLOSED = 50
|
||||
} state;
|
||||
|
||||
/* State of the data stream read. */
|
||||
_output_dnssim_read_state_t read_state;
|
||||
|
||||
/* Total length of the expected dns data (either 2 for dnslen, or dnslen itself). */
|
||||
size_t dnsbuf_len;
|
||||
|
||||
/* Current position in the receive dns buffer. */
|
||||
size_t dnsbuf_pos;
|
||||
|
||||
/* Receive buffer used for incomplete messages or dnslen. */
|
||||
char* dnsbuf_data;
|
||||
bool dnsbuf_free_after_use;
|
||||
|
||||
/* Statistics interval in which the handshake is tracked. */
|
||||
output_dnssim_stats_t* stats;
|
||||
|
||||
/* TLS-related data. */
|
||||
_output_dnssim_tls_ctx_t* tls;
|
||||
|
||||
/* HTTP/2-related data. */
|
||||
_output_dnssim_http2_ctx_t* http2;
|
||||
|
||||
/* Prevents immediate closure of connection. Instead, connection is moved
|
||||
* to CLOSE_REQUESTED state and setter of this flag is responsible for
|
||||
* closing the connection when clearing this flag. */
|
||||
bool prevent_close;
|
||||
};
|
||||
|
||||
/*
|
||||
* Client structure.
|
||||
*/
|
||||
|
||||
struct _output_dnssim_client {
|
||||
/* Dnssim component this client belongs to. */
|
||||
output_dnssim_t* dnssim;
|
||||
|
||||
/* List of connections.
|
||||
* Multiple connections may be used (e.g. some are already closed for writing).
|
||||
*/
|
||||
_output_dnssim_connection_t* conn;
|
||||
|
||||
/* List of queries that are pending to be sent over any available connection. */
|
||||
_output_dnssim_query_t* pending;
|
||||
|
||||
/* TLS-ticket for session resumption. */
|
||||
gnutls_datum_t tls_ticket;
|
||||
};
|
||||
|
||||
/*
|
||||
* DnsSim-related structures.
|
||||
*/
|
||||
|
||||
typedef struct _output_dnssim_source _output_dnssim_source_t;
|
||||
struct _output_dnssim_source {
|
||||
_output_dnssim_source_t* next;
|
||||
struct sockaddr_storage addr;
|
||||
};
|
||||
|
||||
typedef struct _output_dnssim _output_dnssim_t;
|
||||
struct _output_dnssim {
|
||||
output_dnssim_t pub;
|
||||
|
||||
uv_loop_t loop;
|
||||
uv_timer_t stats_timer;
|
||||
|
||||
struct sockaddr_storage target;
|
||||
_output_dnssim_source_t* source;
|
||||
output_dnssim_transport_t transport;
|
||||
|
||||
char h2_uri_authority[_MAX_URI_LEN];
|
||||
char h2_uri_path[_MAX_URI_LEN];
|
||||
bool h2_zero_out_msgid;
|
||||
output_dnssim_h2_method_t h2_method;
|
||||
|
||||
/* Array of clients, mapped by client ID (ranges from 0 to max_clients). */
|
||||
_output_dnssim_client_t* client_arr;
|
||||
|
||||
gnutls_priority_t* tls_priority;
|
||||
gnutls_certificate_credentials_t tls_cred;
|
||||
char wire_buf[WIRE_BUF_SIZE]; /* thread-local buffer for processing tls input */
|
||||
};
|
||||
|
||||
/* Provides data for HTTP/2 data frames. */
|
||||
typedef struct {
|
||||
const uint8_t* buf;
|
||||
size_t len;
|
||||
} _output_dnssim_https2_data_provider_t;
|
||||
|
||||
/*
|
||||
* Forward function declarations.
|
||||
*/
|
||||
|
||||
int _output_dnssim_bind_before_connect(output_dnssim_t* self, uv_handle_t* handle);
|
||||
int _output_dnssim_create_query_udp(output_dnssim_t* self, _output_dnssim_request_t* req);
|
||||
int _output_dnssim_create_query_tcp(output_dnssim_t* self, _output_dnssim_request_t* req);
|
||||
void _output_dnssim_close_query_udp(_output_dnssim_query_udp_t* qry);
|
||||
void _output_dnssim_close_query_tcp(_output_dnssim_query_tcp_t* qry);
|
||||
int _output_dnssim_answers_request(_output_dnssim_request_t* req, core_object_dns_t* response);
|
||||
void _output_dnssim_request_answered(_output_dnssim_request_t* req, core_object_dns_t* msg);
|
||||
void _output_dnssim_maybe_free_request(_output_dnssim_request_t* req);
|
||||
void _output_dnssim_on_uv_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
|
||||
void _output_dnssim_create_request(output_dnssim_t* self, _output_dnssim_client_t* client, core_object_payload_t* payload);
|
||||
int _output_dnssim_handle_pending_queries(_output_dnssim_client_t* client);
|
||||
int _output_dnssim_tcp_connect(output_dnssim_t* self, _output_dnssim_connection_t* conn);
|
||||
void _output_dnssim_tcp_close(_output_dnssim_connection_t* conn);
|
||||
void _output_dnssim_tcp_write_query(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry);
|
||||
void _output_dnssim_conn_close(_output_dnssim_connection_t* conn);
|
||||
void _output_dnssim_conn_idle(_output_dnssim_connection_t* conn);
|
||||
int _output_dnssim_handle_pending_queries(_output_dnssim_client_t* client);
|
||||
void _output_dnssim_conn_activate(_output_dnssim_connection_t* conn);
|
||||
void _output_dnssim_conn_maybe_free(_output_dnssim_connection_t* conn);
|
||||
void _output_dnssim_read_dns_stream(_output_dnssim_connection_t* conn, size_t len, const char* data);
|
||||
void _output_dnssim_read_dnsmsg(_output_dnssim_connection_t* conn, size_t len, const char* data);
|
||||
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
int _output_dnssim_create_query_tls(output_dnssim_t* self, _output_dnssim_request_t* req);
|
||||
void _output_dnssim_close_query_tls(_output_dnssim_query_tcp_t* qry);
|
||||
int _output_dnssim_tls_init(_output_dnssim_connection_t* conn);
|
||||
void _output_dnssim_tls_process_input_data(_output_dnssim_connection_t* conn);
|
||||
void _output_dnssim_tls_close(_output_dnssim_connection_t* conn);
|
||||
void _output_dnssim_tls_write_query(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry);
|
||||
|
||||
int _output_dnssim_create_query_https2(output_dnssim_t* self, _output_dnssim_request_t* req);
|
||||
void _output_dnssim_close_query_https2(_output_dnssim_query_tcp_t* qry);
|
||||
int _output_dnssim_https2_init(_output_dnssim_connection_t* conn);
|
||||
int _output_dnssim_https2_setup(_output_dnssim_connection_t* conn);
|
||||
void _output_dnssim_https2_process_input_data(_output_dnssim_connection_t* conn, size_t len, const char* data);
|
||||
void _output_dnssim_https2_close(_output_dnssim_connection_t* conn);
|
||||
void _output_dnssim_https2_write_query(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020, CZ.NIC, z.s.p.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __dnsjit_output_dnssim_ll_h
|
||||
#define __dnsjit_output_dnssim_ll_h
|
||||
|
||||
#include "core/assert.h"
|
||||
|
||||
/* Utility macros for linked list structures.
|
||||
*
|
||||
* - "list" is the pointer to the first node of the linked list
|
||||
* - "list" can be NULL if there are no nodes
|
||||
* - every node has "next", which points to the next node (can be NULL)
|
||||
*/
|
||||
|
||||
/* Append a node to the list.
|
||||
*
|
||||
* Only a single node can be appended - node->next must be NULL.
|
||||
*/
|
||||
#define _ll_append(list, node) \
|
||||
{ \
|
||||
glassert((node)->next == NULL, "node->next must be null when appending"); \
|
||||
if ((list) == NULL) \
|
||||
(list) = (node); \
|
||||
else if ((node) != NULL) { \
|
||||
typeof(list) _current = (list); \
|
||||
while (_current->next != NULL) \
|
||||
_current = _current->next; \
|
||||
_current->next = node; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Remove a node from the list.
|
||||
*
|
||||
* In strict mode, the node must be present in the list.
|
||||
*/
|
||||
#define _ll_remove_template(list, node, strict) \
|
||||
{ \
|
||||
if (strict) \
|
||||
glassert((list), "list can't be null when removing nodes"); \
|
||||
if ((list) != NULL && (node) != NULL) { \
|
||||
if ((list) == (node)) { \
|
||||
(list) = (node)->next; \
|
||||
(node)->next = NULL; \
|
||||
} else { \
|
||||
typeof(list) _current = (list); \
|
||||
while (_current != NULL && _current->next != (node)) { \
|
||||
if (strict) \
|
||||
glassert((_current->next), "list doesn't contain the node to be removed"); \
|
||||
_current = _current->next; \
|
||||
} \
|
||||
if (_current != NULL) { \
|
||||
_current->next = (node)->next; \
|
||||
(node)->next = NULL; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Remove a node from the list. */
|
||||
#define _ll_remove(list, node) _ll_remove_template((list), (node), true)
|
||||
|
||||
/* Remove a node from the list if it's present. */
|
||||
#define _ll_try_remove(list, node) _ll_remove_template((list), (node), false)
|
||||
|
||||
#endif
|
|
@ -1,356 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020, CZ.NIC, z.s.p.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "output/dnssim.h"
|
||||
#include "output/dnssim/internal.h"
|
||||
#include "output/dnssim/ll.h"
|
||||
#include "core/assert.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static core_log_t _log = LOG_T_INIT("output.dnssim");
|
||||
|
||||
static void _move_queries_to_pending(_output_dnssim_query_tcp_t* qry)
|
||||
{
|
||||
_output_dnssim_query_tcp_t* qry_tmp;
|
||||
while (qry != NULL) {
|
||||
mlassert(qry->conn, "query must be associated with conn");
|
||||
mlassert(qry->conn->state == _OUTPUT_DNSSIM_CONN_CLOSED, "conn must be closed");
|
||||
mlassert(qry->conn->client, "conn must be associated with client");
|
||||
qry_tmp = (_output_dnssim_query_tcp_t*)qry->qry.next;
|
||||
qry->qry.next = NULL;
|
||||
_ll_append(qry->conn->client->pending, &qry->qry);
|
||||
qry->conn = NULL;
|
||||
qry->qry.state = _OUTPUT_DNSSIM_QUERY_ORPHANED;
|
||||
qry->stream_id = -1;
|
||||
qry->recv_buf_len = 0;
|
||||
if (qry->recv_buf != NULL) {
|
||||
free(qry->recv_buf);
|
||||
qry->recv_buf = NULL;
|
||||
}
|
||||
qry = qry_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static void _on_tcp_closed(uv_handle_t* handle)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)handle->data;
|
||||
mlassert(conn, "conn is nil");
|
||||
conn->state = _OUTPUT_DNSSIM_CONN_CLOSED;
|
||||
|
||||
/* Orphan any queries that are still unresolved. */
|
||||
_move_queries_to_pending((_output_dnssim_query_tcp_t*)conn->queued);
|
||||
conn->queued = NULL;
|
||||
_move_queries_to_pending((_output_dnssim_query_tcp_t*)conn->sent);
|
||||
conn->sent = NULL;
|
||||
|
||||
/* TODO Improve client re-connect behavior in case the connection fails to
|
||||
* establish. Currently, queries are orphaned and attempted to be re-sent
|
||||
* along with the next query that triggers a new connection.
|
||||
*
|
||||
* Attempting to establish new connection immediately leads to performance
|
||||
* issues if the number of these attempts doesn't have upper limit. */
|
||||
///* Ensure orhpaned queries are re-sent over a different connection. */
|
||||
//if (_output_dnssim_handle_pending_queries(conn->client) != 0)
|
||||
// mlinfo("tcp: orphaned queries failed to be re-sent");
|
||||
|
||||
mlassert(conn->handle, "conn must have tcp handle when closing it");
|
||||
free(conn->handle);
|
||||
conn->handle = NULL;
|
||||
_output_dnssim_conn_maybe_free(conn);
|
||||
}
|
||||
|
||||
static void _on_tcp_query_written(uv_write_t* wr_req, int status)
|
||||
{
|
||||
_output_dnssim_query_tcp_t* qry = (_output_dnssim_query_tcp_t*)wr_req->data;
|
||||
mlassert(qry, "qry/wr_req->data is nil");
|
||||
mlassert(qry->conn, "query must be associated with connection");
|
||||
_output_dnssim_connection_t* conn = qry->conn;
|
||||
|
||||
free(((_output_dnssim_query_tcp_t*)qry)->bufs[0].base);
|
||||
|
||||
if (qry->qry.state == _OUTPUT_DNSSIM_QUERY_PENDING_CLOSE) {
|
||||
qry->qry.state = status < 0 ? _OUTPUT_DNSSIM_QUERY_WRITE_FAILED : _OUTPUT_DNSSIM_QUERY_SENT;
|
||||
_output_dnssim_request_t* req = qry->qry.req;
|
||||
_output_dnssim_close_query_tcp(qry);
|
||||
_output_dnssim_maybe_free_request(req);
|
||||
qry = NULL;
|
||||
}
|
||||
|
||||
if (status < 0) {
|
||||
if (status != UV_ECANCELED)
|
||||
mlinfo("tcp write failed: %s", uv_strerror(status));
|
||||
if (qry != NULL)
|
||||
qry->qry.state = _OUTPUT_DNSSIM_QUERY_WRITE_FAILED;
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
if (qry == NULL)
|
||||
return;
|
||||
|
||||
/* Mark query as sent and assign it to connection. */
|
||||
mlassert(qry->qry.state == _OUTPUT_DNSSIM_QUERY_PENDING_WRITE_CB, "invalid query state");
|
||||
qry->qry.state = _OUTPUT_DNSSIM_QUERY_SENT;
|
||||
if (qry->conn->state == _OUTPUT_DNSSIM_CONN_ACTIVE) {
|
||||
mlassert(qry->conn->queued, "conn has no queued queries");
|
||||
_ll_remove(qry->conn->queued, &qry->qry);
|
||||
_ll_append(qry->conn->sent, &qry->qry);
|
||||
}
|
||||
}
|
||||
|
||||
void _output_dnssim_tcp_write_query(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry)
|
||||
{
|
||||
mlassert(qry, "qry can't be null");
|
||||
mlassert(qry->qry.state == _OUTPUT_DNSSIM_QUERY_PENDING_WRITE, "qry must be pending write");
|
||||
mlassert(qry->qry.req, "req can't be null");
|
||||
mlassert(qry->qry.req->dns_q, "dns_q can't be null");
|
||||
mlassert(qry->qry.req->dns_q->obj_prev, "payload can't be null");
|
||||
mlassert(conn, "conn can't be null");
|
||||
mlassert(conn->state == _OUTPUT_DNSSIM_CONN_ACTIVE, "connection state != ACTIVE");
|
||||
mlassert(conn->client, "conn must be associated with client");
|
||||
mlassert(conn->client->pending, "conn has no pending queries");
|
||||
|
||||
mldebug("tcp write dnsmsg id: %04x", qry->qry.req->dns_q->id);
|
||||
|
||||
core_object_payload_t* payload = (core_object_payload_t*)qry->qry.req->dns_q->obj_prev;
|
||||
uint16_t* len;
|
||||
mlfatal_oom(len = malloc(sizeof(uint16_t)));
|
||||
*len = htons(payload->len);
|
||||
qry->bufs[0] = uv_buf_init((char*)len, 2);
|
||||
qry->bufs[1] = uv_buf_init((char*)payload->payload, payload->len);
|
||||
|
||||
qry->conn = conn;
|
||||
_ll_remove(conn->client->pending, &qry->qry);
|
||||
_ll_append(conn->queued, &qry->qry);
|
||||
|
||||
/* Stop idle timer, since there are queries to answer now. */
|
||||
if (conn->idle_timer != NULL) {
|
||||
conn->is_idle = false;
|
||||
uv_timer_stop(conn->idle_timer);
|
||||
}
|
||||
|
||||
qry->write_req.data = (void*)qry;
|
||||
uv_write(&qry->write_req, (uv_stream_t*)conn->handle, qry->bufs, 2, _on_tcp_query_written);
|
||||
qry->qry.state = _OUTPUT_DNSSIM_QUERY_PENDING_WRITE_CB;
|
||||
}
|
||||
|
||||
static void _on_tcp_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)handle->data;
|
||||
output_dnssim_t* self = conn->client->dnssim;
|
||||
|
||||
if (nread > 0) {
|
||||
mldebug("tcp nread: %d", nread);
|
||||
switch (_self->transport) {
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TCP:
|
||||
_output_dnssim_read_dns_stream(conn, nread, buf->base);
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TLS:
|
||||
case OUTPUT_DNSSIM_TRANSPORT_HTTPS2:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
mlassert(conn->tls, "con must have tls ctx");
|
||||
conn->tls->buf = (uint8_t*)buf->base;
|
||||
conn->tls->buf_pos = 0;
|
||||
conn->tls->buf_len = nread;
|
||||
_output_dnssim_tls_process_input_data(conn);
|
||||
#else
|
||||
mlfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
mlfatal("unsupported transport");
|
||||
break;
|
||||
}
|
||||
} else if (nread < 0) {
|
||||
if (nread != UV_EOF)
|
||||
mlinfo("tcp conn unexpected close: %s", uv_strerror(nread));
|
||||
_output_dnssim_conn_close(conn);
|
||||
}
|
||||
|
||||
if (buf->base != NULL)
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
static void _on_tcp_connected(uv_connect_t* conn_req, int status)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)conn_req->handle->data;
|
||||
mlassert(conn, "conn is nil");
|
||||
|
||||
free(conn_req);
|
||||
|
||||
if (status < 0) {
|
||||
mldebug("tcp connect failed: %s", uv_strerror(status));
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
mlassert(conn->state == _OUTPUT_DNSSIM_CONN_TCP_HANDSHAKE, "connection state != TCP_HANDSHAKE");
|
||||
int ret = uv_read_start((uv_stream_t*)conn->handle, _output_dnssim_on_uv_alloc, _on_tcp_read);
|
||||
if (ret < 0) {
|
||||
mlwarning("tcp uv_read_start() failed: %s", uv_strerror(ret));
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
mldebug("tcp connected");
|
||||
mlassert(conn->client, "conn must be associated with a client");
|
||||
mlassert(conn->client->dnssim, "client must be associated with dnssim");
|
||||
output_dnssim_t* self = conn->client->dnssim;
|
||||
switch (_self->transport) {
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TCP:
|
||||
_output_dnssim_conn_activate(conn);
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TLS:
|
||||
case OUTPUT_DNSSIM_TRANSPORT_HTTPS2:
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
mldebug("init tls handshake");
|
||||
_output_dnssim_tls_process_input_data(conn); /* Initiate TLS handshake. */
|
||||
#else
|
||||
mlfatal(DNSSIM_MIN_GNUTLS_ERRORMSG);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
lfatal("unsupported transport protocol");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _on_connection_timeout(uv_timer_t* handle)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)handle->data;
|
||||
_output_dnssim_conn_close(conn);
|
||||
}
|
||||
|
||||
int _output_dnssim_tcp_connect(output_dnssim_t* self, _output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(conn, "connection can't be null");
|
||||
lassert(conn->handle == NULL, "connection already has a handle");
|
||||
lassert(conn->handshake_timer == NULL, "connection already has a handshake timer");
|
||||
lassert(conn->idle_timer == NULL, "connection already has idle timer");
|
||||
lassert(conn->state == _OUTPUT_DNSSIM_CONN_INITIALIZED, "connection state != INITIALIZED");
|
||||
|
||||
lfatal_oom(conn->handle = malloc(sizeof(uv_tcp_t)));
|
||||
conn->handle->data = (void*)conn;
|
||||
int ret = uv_tcp_init(&_self->loop, conn->handle);
|
||||
if (ret < 0) {
|
||||
lwarning("failed to init uv_tcp_t");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
ret = _output_dnssim_bind_before_connect(self, (uv_handle_t*)conn->handle);
|
||||
if (ret < 0)
|
||||
goto failure;
|
||||
|
||||
/* Set connection parameters. */
|
||||
ret = uv_tcp_nodelay(conn->handle, 1);
|
||||
if (ret < 0)
|
||||
lwarning("tcp: failed to set TCP_NODELAY: %s", uv_strerror(ret));
|
||||
|
||||
/* Set connection handshake timeout. */
|
||||
lfatal_oom(conn->handshake_timer = malloc(sizeof(uv_timer_t)));
|
||||
uv_timer_init(&_self->loop, conn->handshake_timer);
|
||||
conn->handshake_timer->data = (void*)conn;
|
||||
uv_timer_start(conn->handshake_timer, _on_connection_timeout, self->handshake_timeout_ms, 0);
|
||||
|
||||
/* Set idle connection timer. */
|
||||
if (self->idle_timeout_ms > 0) {
|
||||
lfatal_oom(conn->idle_timer = malloc(sizeof(uv_timer_t)));
|
||||
uv_timer_init(&_self->loop, conn->idle_timer);
|
||||
conn->idle_timer->data = (void*)conn;
|
||||
|
||||
/* Start and stop the timer to set the repeat value without running the timer. */
|
||||
uv_timer_start(conn->idle_timer, _on_connection_timeout, self->idle_timeout_ms, self->idle_timeout_ms);
|
||||
uv_timer_stop(conn->idle_timer);
|
||||
}
|
||||
|
||||
mldebug("tcp connecting");
|
||||
uv_connect_t* conn_req;
|
||||
lfatal_oom(conn_req = malloc(sizeof(uv_connect_t)));
|
||||
ret = uv_tcp_connect(conn_req, conn->handle, (struct sockaddr*)&_self->target, _on_tcp_connected);
|
||||
if (ret < 0)
|
||||
goto failure;
|
||||
|
||||
conn->stats->conn_handshakes++;
|
||||
conn->client->dnssim->stats_sum->conn_handshakes++;
|
||||
conn->state = _OUTPUT_DNSSIM_CONN_TCP_HANDSHAKE;
|
||||
return 0;
|
||||
failure:
|
||||
_output_dnssim_conn_close(conn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _output_dnssim_tcp_close(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn can't be nil");
|
||||
|
||||
if (conn->handle != NULL) {
|
||||
uv_read_stop((uv_stream_t*)conn->handle);
|
||||
uv_close((uv_handle_t*)conn->handle, _on_tcp_closed);
|
||||
}
|
||||
}
|
||||
|
||||
int _output_dnssim_create_query_tcp(output_dnssim_t* self, _output_dnssim_request_t* req)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(req, "req is nil");
|
||||
lassert(req->client, "request must have a client associated with it");
|
||||
|
||||
_output_dnssim_query_tcp_t* qry;
|
||||
|
||||
lfatal_oom(qry = calloc(1, sizeof(_output_dnssim_query_tcp_t)));
|
||||
|
||||
qry->qry.transport = OUTPUT_DNSSIM_TRANSPORT_TCP;
|
||||
qry->qry.req = req;
|
||||
qry->qry.state = _OUTPUT_DNSSIM_QUERY_PENDING_WRITE;
|
||||
req->qry = &qry->qry; // TODO change when adding support for multiple Qs for req
|
||||
_ll_append(req->client->pending, &qry->qry);
|
||||
|
||||
return _output_dnssim_handle_pending_queries(req->client);
|
||||
}
|
||||
|
||||
void _output_dnssim_close_query_tcp(_output_dnssim_query_tcp_t* qry)
|
||||
{
|
||||
mlassert(qry, "qry can't be null");
|
||||
mlassert(qry->qry.req, "query must be part of a request");
|
||||
_output_dnssim_request_t* req = qry->qry.req;
|
||||
mlassert(req->client, "request must belong to a client");
|
||||
|
||||
if ((qry->qry.state == _OUTPUT_DNSSIM_QUERY_PENDING_WRITE_CB || qry->qry.state == _OUTPUT_DNSSIM_QUERY_PENDING_CLOSE)) {
|
||||
/* Query can't be freed until uv callback is called. */
|
||||
qry->qry.state = _OUTPUT_DNSSIM_QUERY_PENDING_CLOSE;
|
||||
return;
|
||||
}
|
||||
|
||||
_ll_try_remove(req->client->pending, &qry->qry);
|
||||
if (qry->conn) {
|
||||
_output_dnssim_connection_t* conn = qry->conn;
|
||||
_ll_try_remove(conn->queued, &qry->qry); /* edge-case of cancelled queries */
|
||||
_ll_try_remove(conn->sent, &qry->qry);
|
||||
qry->conn = NULL;
|
||||
_output_dnssim_conn_idle(conn);
|
||||
}
|
||||
|
||||
_ll_remove(req->qry, &qry->qry);
|
||||
free(qry);
|
||||
}
|
|
@ -1,475 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020, CZ.NIC, z.s.p.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "output/dnssim.h"
|
||||
#include "output/dnssim/internal.h"
|
||||
#include "output/dnssim/ll.h"
|
||||
#include "core/assert.h"
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <string.h>
|
||||
|
||||
#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b)) /** Minimum of two numbers **/
|
||||
#endif
|
||||
|
||||
static core_log_t _log = LOG_T_INIT("output.dnssim");
|
||||
|
||||
struct async_write_ctx {
|
||||
uv_write_t write_req;
|
||||
_output_dnssim_connection_t* conn;
|
||||
char buf[];
|
||||
};
|
||||
|
||||
static int _tls_handshake(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->tls, "conn must have tls context");
|
||||
mlassert(conn->client, "conn must belong to a client");
|
||||
mlassert(conn->state <= _OUTPUT_DNSSIM_CONN_TLS_HANDSHAKE, "conn in invalid state");
|
||||
|
||||
/* Set TLS session resumption ticket if available. */
|
||||
if (conn->state < _OUTPUT_DNSSIM_CONN_TLS_HANDSHAKE && conn->client->tls_ticket.size != 0) {
|
||||
gnutls_datum_t* ticket = &conn->client->tls_ticket;
|
||||
gnutls_session_set_data(conn->tls->session, ticket->data, ticket->size);
|
||||
}
|
||||
conn->state = _OUTPUT_DNSSIM_CONN_TLS_HANDSHAKE;
|
||||
|
||||
return gnutls_handshake(conn->tls->session);
|
||||
}
|
||||
|
||||
void _output_dnssim_tls_process_input_data(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->client, "conn must have client");
|
||||
mlassert(conn->client->dnssim, "client must have dnssim");
|
||||
mlassert(conn->tls, "conn must have tls ctx");
|
||||
|
||||
if (conn->state >= _OUTPUT_DNSSIM_CONN_CLOSING)
|
||||
return;
|
||||
|
||||
output_dnssim_t* self = conn->client->dnssim;
|
||||
|
||||
/* Ensure TLS handshake is performed before receiving data.
|
||||
* See https://www.gnutls.org/manual/html_node/TLS-handshake.html */
|
||||
while (conn->state <= _OUTPUT_DNSSIM_CONN_TLS_HANDSHAKE) {
|
||||
int err = _tls_handshake(conn);
|
||||
mldebug("tls handshake returned: %s", gnutls_strerror(err));
|
||||
if (err == GNUTLS_E_SUCCESS) {
|
||||
if (gnutls_session_is_resumed(conn->tls->session))
|
||||
conn->stats->conn_resumed++;
|
||||
if (_self->transport == OUTPUT_DNSSIM_TRANSPORT_HTTPS2) {
|
||||
if (_output_dnssim_https2_setup(conn) < 0) {
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_output_dnssim_conn_activate(conn);
|
||||
break;
|
||||
} else if (err == GNUTLS_E_AGAIN) {
|
||||
return; /* Wait for more data */
|
||||
} else if (err == GNUTLS_E_FATAL_ALERT_RECEIVED) {
|
||||
gnutls_alert_description_t alert = gnutls_alert_get(conn->tls->session);
|
||||
mlwarning("gnutls_handshake failed: %s", gnutls_alert_get_name(alert));
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
} else if (gnutls_error_is_fatal(err)) {
|
||||
mlwarning("gnutls_handshake failed: %s", gnutls_strerror_name(err));
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* See https://gnutls.org/manual/html_node/Data-transfer-and-termination.html#Data-transfer-and-termination */
|
||||
while (true) {
|
||||
/* Connection might have been closed due to an error, don't try to use it. */
|
||||
if (conn->state < _OUTPUT_DNSSIM_CONN_ACTIVE || conn->state >= _OUTPUT_DNSSIM_CONN_CLOSING)
|
||||
return;
|
||||
|
||||
ssize_t count = gnutls_record_recv(conn->tls->session, _self->wire_buf, WIRE_BUF_SIZE);
|
||||
if (count > 0) {
|
||||
switch (_self->transport) {
|
||||
case OUTPUT_DNSSIM_TRANSPORT_TLS:
|
||||
_output_dnssim_read_dns_stream(conn, count, _self->wire_buf);
|
||||
break;
|
||||
case OUTPUT_DNSSIM_TRANSPORT_HTTPS2:
|
||||
_output_dnssim_https2_process_input_data(conn, count, _self->wire_buf);
|
||||
break;
|
||||
default:
|
||||
lfatal("unsupported transport layer");
|
||||
break;
|
||||
}
|
||||
} else if (count == GNUTLS_E_AGAIN) {
|
||||
if (conn->tls->buf_pos == conn->tls->buf_len) {
|
||||
/* See https://www.gnutls.org/manual/html_node/Asynchronous-operation.html */
|
||||
break; /* No more data available in this libuv buffer */
|
||||
}
|
||||
continue;
|
||||
} else if (count == GNUTLS_E_INTERRUPTED) {
|
||||
continue;
|
||||
} else if (count == GNUTLS_E_REHANDSHAKE) {
|
||||
continue; /* Ignore rehandshake request. */
|
||||
} else if (count < 0) {
|
||||
mlwarning("gnutls_record_recv failed: %s", gnutls_strerror_name(count));
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
} else if (count == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
mlassert(conn->tls->buf_len == conn->tls->buf_pos, "tls didn't read the entire buffer");
|
||||
}
|
||||
|
||||
static ssize_t _tls_pull(gnutls_transport_ptr_t ptr, void* buf, size_t len)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)ptr;
|
||||
mlassert(conn != NULL, "conn is null");
|
||||
mlassert(conn->tls != NULL, "conn must have tls ctx");
|
||||
|
||||
ssize_t avail = conn->tls->buf_len - conn->tls->buf_pos;
|
||||
if (avail <= 0) {
|
||||
mldebug("tls pull: no more data");
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t transfer = MIN(avail, len);
|
||||
memcpy(buf, conn->tls->buf + conn->tls->buf_pos, transfer);
|
||||
conn->tls->buf_pos += transfer;
|
||||
return transfer;
|
||||
}
|
||||
|
||||
static void _tls_on_write_complete(uv_write_t* req, int status)
|
||||
{
|
||||
mlassert(req->data != NULL, "uv_write req has no data pointer");
|
||||
struct async_write_ctx* async_ctx = (struct async_write_ctx*)req->data;
|
||||
_output_dnssim_connection_t* conn = async_ctx->conn;
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->tls, "conn must have tls ctx");
|
||||
mlassert(conn->tls->write_queue_size > 0, "invalid write_queue_size: %d", conn->tls->write_queue_size);
|
||||
conn->tls->write_queue_size -= 1;
|
||||
free(req->data);
|
||||
|
||||
if (status < 0)
|
||||
_output_dnssim_conn_close(conn);
|
||||
}
|
||||
|
||||
static ssize_t _tls_vec_push(gnutls_transport_ptr_t ptr, const giovec_t* iov, int iovcnt)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)ptr;
|
||||
mlassert(conn != NULL, "conn is null");
|
||||
mlassert(conn->tls != NULL, "conn must have tls ctx");
|
||||
|
||||
if (iovcnt == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* This is a little bit complicated. There are two different writes:
|
||||
* 1. Immediate, these don't need to own the buffered data and return immediately
|
||||
* 2. Asynchronous, these need to own the buffers until the write completes
|
||||
* In order to avoid copying the buffer, an immediate write is tried first if possible.
|
||||
* If it isn't possible to write the data without queueing, an asynchronous write
|
||||
* is created (with copied buffered data).
|
||||
*/
|
||||
|
||||
size_t total_len = 0;
|
||||
uv_buf_t uv_buf[iovcnt];
|
||||
int i;
|
||||
for (i = 0; i < iovcnt; ++i) {
|
||||
uv_buf[i].base = iov[i].iov_base;
|
||||
uv_buf[i].len = iov[i].iov_len;
|
||||
total_len += iov[i].iov_len;
|
||||
}
|
||||
|
||||
/* Try to perform the immediate write first to avoid copy */
|
||||
int ret = 0;
|
||||
if (conn->tls->write_queue_size == 0) {
|
||||
ret = uv_try_write((uv_stream_t*)conn->handle, uv_buf, iovcnt);
|
||||
/* from libuv documentation -
|
||||
uv_try_write will return either:
|
||||
> 0: number of bytes written (can be less than the supplied buffer size).
|
||||
< 0: negative error code (UV_EAGAIN is returned if no data can be sent immediately).
|
||||
*/
|
||||
if (ret == total_len) {
|
||||
/* All the data were buffered by libuv.
|
||||
* Return. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret < 0 && ret != UV_EAGAIN) {
|
||||
/* uv_try_write() has returned error code other then UV_EAGAIN.
|
||||
* Return. */
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
/* Since we are here expression below is true
|
||||
* (ret != total_len) && (ret >= 0 || ret == UV_EAGAIN)
|
||||
* or the same
|
||||
* (ret != total_len && ret >= 0) || (ret != total_len && ret == UV_EAGAIN)
|
||||
* i.e. either occurs partial write or UV_EAGAIN.
|
||||
* Proceed and copy data amount to owned memory and perform async write.
|
||||
*/
|
||||
if (ret == UV_EAGAIN) {
|
||||
/* No data were buffered, so we must buffer all the data. */
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fallback when the queue is full, and it's not possible to do an immediate write */
|
||||
char* p = malloc(sizeof(struct async_write_ctx) + total_len - ret);
|
||||
if (p != NULL) {
|
||||
struct async_write_ctx* async_ctx = (struct async_write_ctx*)p;
|
||||
async_ctx->conn = conn;
|
||||
char* buf = async_ctx->buf;
|
||||
/* Skip data written in the partial write */
|
||||
size_t to_skip = ret;
|
||||
/* Copy the buffer into owned memory */
|
||||
size_t off = 0;
|
||||
int i;
|
||||
for (i = 0; i < iovcnt; ++i) {
|
||||
if (to_skip > 0) {
|
||||
/* Ignore current buffer if it's all skipped */
|
||||
if (to_skip >= uv_buf[i].len) {
|
||||
to_skip -= uv_buf[i].len;
|
||||
continue;
|
||||
}
|
||||
/* Skip only part of the buffer */
|
||||
uv_buf[i].base += to_skip;
|
||||
uv_buf[i].len -= to_skip;
|
||||
to_skip = 0;
|
||||
}
|
||||
memcpy(buf + off, uv_buf[i].base, uv_buf[i].len);
|
||||
off += uv_buf[i].len;
|
||||
}
|
||||
uv_buf[0].base = buf;
|
||||
uv_buf[0].len = off;
|
||||
|
||||
/* Create an asynchronous write request */
|
||||
uv_write_t* write_req = &async_ctx->write_req;
|
||||
memset(write_req, 0, sizeof(uv_write_t));
|
||||
write_req->data = p;
|
||||
|
||||
/* Perform an asynchronous write with a callback */
|
||||
if (uv_write(write_req, (uv_stream_t*)conn->handle, uv_buf, 1, _tls_on_write_complete) == 0) {
|
||||
ret = total_len;
|
||||
conn->tls->write_queue_size += 1;
|
||||
} else {
|
||||
free(p);
|
||||
errno = EIO;
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
errno = ENOMEM;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _tls_pull_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
|
||||
{
|
||||
_output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)ptr;
|
||||
mlassert(conn != NULL, "conn is null");
|
||||
mlassert(conn->tls != NULL, "conn must have tls ctx");
|
||||
|
||||
ssize_t avail = conn->tls->buf_len - conn->tls->buf_pos;
|
||||
if (avail <= 0) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
return avail;
|
||||
}
|
||||
|
||||
int _output_dnssim_tls_init(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn is nil");
|
||||
mlassert(conn->tls == NULL, "conn already has tls context");
|
||||
|
||||
int ret;
|
||||
mlfatal_oom(conn->tls = malloc(sizeof(_output_dnssim_tls_ctx_t)));
|
||||
conn->tls->buf = NULL;
|
||||
conn->tls->buf_len = 0;
|
||||
conn->tls->buf_pos = 0;
|
||||
conn->tls->write_queue_size = 0;
|
||||
|
||||
ret = gnutls_init(&conn->tls->session, GNUTLS_CLIENT | GNUTLS_NONBLOCK);
|
||||
if (ret < 0) {
|
||||
mldebug("failed gnutls_init() (%s)", gnutls_strerror(ret));
|
||||
free(conn->tls);
|
||||
conn->tls = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
output_dnssim_t* self = conn->client->dnssim;
|
||||
if (_self->tls_priority == NULL) {
|
||||
ret = gnutls_set_default_priority(conn->tls->session);
|
||||
if (ret < 0) {
|
||||
mldebug("failed gnutls_set_default_priority() (%s)", gnutls_strerror(ret));
|
||||
gnutls_deinit(conn->tls->session);
|
||||
free(conn->tls);
|
||||
conn->tls = 0;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ret = gnutls_priority_set(conn->tls->session, *_self->tls_priority);
|
||||
if (ret < 0) {
|
||||
mldebug("failed gnutls_priority_set() (%s)", gnutls_strerror(ret));
|
||||
gnutls_deinit(conn->tls->session);
|
||||
free(conn->tls);
|
||||
conn->tls = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = gnutls_credentials_set(conn->tls->session, GNUTLS_CRD_CERTIFICATE, _self->tls_cred);
|
||||
if (ret < 0) {
|
||||
mldebug("failed gnutls_credentials_set() (%s)", gnutls_strerror(ret));
|
||||
gnutls_deinit(conn->tls->session);
|
||||
free(conn->tls);
|
||||
conn->tls = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
gnutls_transport_set_pull_function(conn->tls->session, _tls_pull);
|
||||
gnutls_transport_set_pull_timeout_function(conn->tls->session, _tls_pull_timeout);
|
||||
gnutls_transport_set_vec_push_function(conn->tls->session, _tls_vec_push);
|
||||
gnutls_transport_set_ptr(conn->tls->session, conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _output_dnssim_create_query_tls(output_dnssim_t* self, _output_dnssim_request_t* req)
|
||||
{
|
||||
mlassert_self();
|
||||
lassert(req, "req is nil");
|
||||
lassert(req->client, "request must have a client associated with it");
|
||||
|
||||
_output_dnssim_query_tcp_t* qry;
|
||||
|
||||
lfatal_oom(qry = calloc(1, sizeof(_output_dnssim_query_tcp_t)));
|
||||
|
||||
qry->qry.transport = OUTPUT_DNSSIM_TRANSPORT_TLS;
|
||||
qry->qry.req = req;
|
||||
qry->qry.state = _OUTPUT_DNSSIM_QUERY_PENDING_WRITE;
|
||||
req->qry = &qry->qry; // TODO change when adding support for multiple Qs for req
|
||||
_ll_append(req->client->pending, &qry->qry);
|
||||
|
||||
return _output_dnssim_handle_pending_queries(req->client);
|
||||
}
|
||||
|
||||
void _output_dnssim_close_query_tls(_output_dnssim_query_tcp_t* qry)
|
||||
{
|
||||
mlassert(qry, "qry can't be null");
|
||||
mlassert(qry->qry.req, "query must be part of a request");
|
||||
_output_dnssim_request_t* req = qry->qry.req;
|
||||
mlassert(req->client, "request must belong to a client");
|
||||
|
||||
_ll_try_remove(req->client->pending, &qry->qry);
|
||||
if (qry->conn) {
|
||||
_output_dnssim_connection_t* conn = qry->conn;
|
||||
_ll_try_remove(conn->sent, &qry->qry);
|
||||
qry->conn = NULL;
|
||||
_output_dnssim_conn_idle(conn);
|
||||
}
|
||||
|
||||
_ll_remove(req->qry, &qry->qry);
|
||||
free(qry);
|
||||
}
|
||||
|
||||
void _output_dnssim_tls_close(_output_dnssim_connection_t* conn)
|
||||
{
|
||||
mlassert(conn, "conn can't be nil");
|
||||
mlassert(conn->tls, "conn must have tls ctx");
|
||||
mlassert(conn->client, "conn must belong to a client");
|
||||
|
||||
/* Try and get a TLS session ticket for potential resumption. */
|
||||
int ret;
|
||||
if (gnutls_session_get_flags(conn->tls->session) & GNUTLS_SFLAGS_SESSION_TICKET) {
|
||||
if (conn->client->tls_ticket.size != 0) {
|
||||
gnutls_free(conn->client->tls_ticket.data);
|
||||
}
|
||||
ret = gnutls_session_get_data2(conn->tls->session, &conn->client->tls_ticket);
|
||||
if (ret < 0) {
|
||||
mldebug("gnutls_session_get_data2 failed: %s", gnutls_strerror(ret));
|
||||
conn->client->tls_ticket.size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
gnutls_deinit(conn->tls->session);
|
||||
_output_dnssim_tcp_close(conn);
|
||||
}
|
||||
|
||||
void _output_dnssim_tls_write_query(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry)
|
||||
{
|
||||
mlassert(qry, "qry can't be null");
|
||||
mlassert(qry->qry.state == _OUTPUT_DNSSIM_QUERY_PENDING_WRITE, "qry must be pending write");
|
||||
mlassert(qry->qry.req, "req can't be null");
|
||||
mlassert(qry->qry.req->dns_q, "dns_q can't be null");
|
||||
mlassert(qry->qry.req->dns_q->obj_prev, "payload can't be null");
|
||||
mlassert(conn, "conn can't be null");
|
||||
mlassert(conn->state == _OUTPUT_DNSSIM_CONN_ACTIVE, "connection state != ACTIVE");
|
||||
mlassert(conn->tls, "conn must have tls ctx");
|
||||
mlassert(conn->client, "conn must be associated with client");
|
||||
mlassert(conn->client->pending, "conn has no pending queries");
|
||||
|
||||
core_object_payload_t* payload = (core_object_payload_t*)qry->qry.req->dns_q->obj_prev;
|
||||
uint16_t len = htons(payload->len);
|
||||
|
||||
gnutls_record_cork(conn->tls->session);
|
||||
ssize_t count = 0;
|
||||
if ((count = gnutls_record_send(conn->tls->session, &len, sizeof(len)) < 0) || (count = gnutls_record_send(conn->tls->session, payload->payload, payload->len) < 0)) {
|
||||
mlwarning("gnutls_record_send failed: %s", gnutls_strerror_name(count));
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
const ssize_t submitted = sizeof(len) + payload->len;
|
||||
|
||||
int ret = gnutls_record_uncork(conn->tls->session, GNUTLS_RECORD_WAIT);
|
||||
if (gnutls_error_is_fatal(ret)) {
|
||||
mlinfo("gnutls_record_uncorck failed: %s", gnutls_strerror_name(ret));
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret != submitted) {
|
||||
mlwarning("gnutls_record_uncork didn't send all data");
|
||||
_output_dnssim_conn_close(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
qry->conn = conn;
|
||||
_ll_remove(conn->client->pending, &qry->qry);
|
||||
_ll_append(conn->sent, &qry->qry);
|
||||
|
||||
/* Stop idle timer, since there are queries to answer now. */
|
||||
if (conn->idle_timer != NULL) {
|
||||
conn->is_idle = false;
|
||||
uv_timer_stop(conn->idle_timer);
|
||||
}
|
||||
|
||||
qry->qry.state = _OUTPUT_DNSSIM_QUERY_SENT;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020, CZ.NIC, z.s.p.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "output/dnssim.h"
|
||||
#include "output/dnssim/internal.h"
|
||||
#include "output/dnssim/ll.h"
|
||||
#include "core/assert.h"
|
||||
|
||||
static core_log_t _log = LOG_T_INIT("output.dnssim");
|
||||
|
||||
static int _process_udp_response(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf)
|
||||
{
|
||||
_output_dnssim_query_udp_t* qry = (_output_dnssim_query_udp_t*)handle->data;
|
||||
_output_dnssim_request_t* req;
|
||||
core_object_payload_t payload = CORE_OBJECT_PAYLOAD_INIT(NULL);
|
||||
core_object_dns_t dns_a = CORE_OBJECT_DNS_INIT(&payload);
|
||||
mlassert(qry, "qry is nil");
|
||||
mlassert(qry->qry.req, "query must be part of a request");
|
||||
req = qry->qry.req;
|
||||
|
||||
payload.payload = (uint8_t*)buf->base;
|
||||
payload.len = nread;
|
||||
|
||||
dns_a.obj_prev = (core_object_t*)&payload;
|
||||
int ret = core_object_dns_parse_header(&dns_a);
|
||||
if (ret != 0) {
|
||||
mldebug("udp response malformed");
|
||||
return _ERR_MALFORMED;
|
||||
}
|
||||
if (dns_a.id != req->dns_q->id) {
|
||||
mldebug("udp response msgid mismatch %x(q) != %x(a)", req->dns_q->id, dns_a.id);
|
||||
return _ERR_MSGID;
|
||||
}
|
||||
if (dns_a.tc == 1) {
|
||||
mldebug("udp response has TC=1");
|
||||
return _ERR_TC;
|
||||
}
|
||||
ret = _output_dnssim_answers_request(req, &dns_a);
|
||||
if (ret != 0) {
|
||||
mlwarning("udp reponse question mismatch");
|
||||
return _ERR_QUESTION;
|
||||
}
|
||||
|
||||
_output_dnssim_request_answered(req, &dns_a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _on_udp_query_recv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags)
|
||||
{
|
||||
if (nread > 0) {
|
||||
mldebug("udp recv: %d", nread);
|
||||
|
||||
// TODO handle TC=1
|
||||
_process_udp_response(handle, nread, buf);
|
||||
}
|
||||
|
||||
if (buf->base != NULL) {
|
||||
free(buf->base);
|
||||
}
|
||||
}
|
||||
|
||||
static void _on_query_udp_closed(uv_handle_t* handle)
|
||||
{
|
||||
_output_dnssim_query_udp_t* qry = (_output_dnssim_query_udp_t*)handle->data;
|
||||
_output_dnssim_request_t* req;
|
||||
mlassert(qry, "qry is nil");
|
||||
mlassert(qry->qry.req, "query must be part of a request");
|
||||
req = qry->qry.req;
|
||||
|
||||
free(qry->handle);
|
||||
|
||||
_ll_remove(req->qry, &qry->qry);
|
||||
free(qry);
|
||||
|
||||
if (req->qry == NULL)
|
||||
_output_dnssim_maybe_free_request(req);
|
||||
}
|
||||
|
||||
void _output_dnssim_close_query_udp(_output_dnssim_query_udp_t* qry)
|
||||
{
|
||||
int ret;
|
||||
mlassert(qry, "qry is nil");
|
||||
|
||||
ret = uv_udp_recv_stop(qry->handle);
|
||||
if (ret < 0) {
|
||||
mldebug("failed uv_udp_recv_stop(): %s", uv_strerror(ret));
|
||||
}
|
||||
|
||||
uv_close((uv_handle_t*)qry->handle, _on_query_udp_closed);
|
||||
}
|
||||
|
||||
int _output_dnssim_create_query_udp(output_dnssim_t* self, _output_dnssim_request_t* req)
|
||||
{
|
||||
int ret;
|
||||
_output_dnssim_query_udp_t* qry;
|
||||
core_object_payload_t* payload;
|
||||
mlassert_self();
|
||||
lassert(req, "req is nil");
|
||||
payload = (core_object_payload_t*)req->dns_q->obj_prev;
|
||||
|
||||
lfatal_oom(qry = calloc(1, sizeof(_output_dnssim_query_udp_t)));
|
||||
lfatal_oom(qry->handle = malloc(sizeof(uv_udp_t)));
|
||||
|
||||
qry->qry.transport = OUTPUT_DNSSIM_TRANSPORT_UDP;
|
||||
qry->qry.req = req;
|
||||
qry->buf = uv_buf_init((char*)payload->payload, payload->len);
|
||||
qry->handle->data = (void*)qry;
|
||||
ret = uv_udp_init(&_self->loop, qry->handle);
|
||||
if (ret < 0) {
|
||||
lwarning("failed to init uv_udp_t");
|
||||
goto failure;
|
||||
}
|
||||
_ll_append(req->qry, &qry->qry);
|
||||
|
||||
ret = _output_dnssim_bind_before_connect(self, (uv_handle_t*)qry->handle);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = uv_udp_try_send(qry->handle, &qry->buf, 1, (struct sockaddr*)&_self->target);
|
||||
if (ret < 0) {
|
||||
lwarning("failed to send udp packet: %s", uv_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// listen for reply
|
||||
ret = uv_udp_recv_start(qry->handle, _output_dnssim_on_uv_alloc, _on_udp_query_recv);
|
||||
if (ret < 0) {
|
||||
lwarning("failed uv_udp_recv_start(): %s", uv_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
failure:
|
||||
free(qry->handle);
|
||||
free(qry);
|
||||
return ret;
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, OARC, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "output/null.h"
|
||||
#include "core/assert.h"
|
||||
#include "core/object/pcap.h"
|
||||
|
||||
static core_log_t _log = LOG_T_INIT("output.null");
|
||||
static output_null_t _defaults = {
|
||||
LOG_T_INIT_OBJ("output.null"),
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
core_log_t* output_null_log()
|
||||
{
|
||||
return &_log;
|
||||
}
|
||||
|
||||
void output_null_init(output_null_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
*self = _defaults;
|
||||
}
|
||||
|
||||
void output_null_destroy(output_null_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
}
|
||||
|
||||
static void _receive(output_null_t* self, const core_object_t* obj)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
self->pkts++;
|
||||
}
|
||||
|
||||
core_receiver_t output_null_receiver()
|
||||
{
|
||||
return (core_receiver_t)_receive;
|
||||
}
|
||||
|
||||
void output_null_run(output_null_t* self, int64_t num)
|
||||
{
|
||||
mlassert_self();
|
||||
|
||||
if (!self->prod) {
|
||||
lfatal("no producer set");
|
||||
}
|
||||
|
||||
if (num > 0) {
|
||||
while (num--) {
|
||||
const core_object_t* obj = self->prod(self->ctx);
|
||||
if (!obj)
|
||||
break;
|
||||
|
||||
self->pkts++;
|
||||
}
|
||||
} else {
|
||||
for (;;) {
|
||||
const core_object_t* obj = self->prod(self->ctx);
|
||||
if (!obj)
|
||||
break;
|
||||
|
||||
self->pkts++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, OARC, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of dnsjit.
|
||||
*
|
||||
* dnsjit is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dnsjit is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//lua:require("dnsjit.core.log")
|
||||
//lua:require("dnsjit.core.receiver_h")
|
||||
//lua:require("dnsjit.core.producer_h")
|
||||
|
||||
typedef struct output_null {
|
||||
core_log_t _log;
|
||||
core_producer_t prod;
|
||||
void* ctx;
|
||||
size_t pkts;
|
||||
} output_null_t;
|
||||
|
||||
core_log_t* output_null_log();
|
||||
void output_null_init(output_null_t* self);
|
||||
void output_null_destroy(output_null_t* self);
|
||||
void output_null_run(output_null_t* self, int64_t num);
|
||||
|
||||
core_receiver_t output_null_receiver();
|
|
@ -17,64 +17,15 @@
|
|||
-- along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
-- dnsjit.output.null
|
||||
-- Output to nothing (/dev/null)
|
||||
-- local output = require("dnsjit.output.null").new()
|
||||
-- Dummy layer to example.output.null
|
||||
--
|
||||
-- Output module for those that doesn't really like packets.
|
||||
-- This module has moved to example.output.null, see examples/modules/output-example in
|
||||
-- dnsjit source repository.
|
||||
module(...,package.seeall)
|
||||
|
||||
require("dnsjit.output.null_h")
|
||||
local ffi = require("ffi")
|
||||
local C = ffi.C
|
||||
|
||||
local t_name = "output_null_t"
|
||||
local output_null_t = ffi.typeof(t_name)
|
||||
local Null = {}
|
||||
|
||||
-- Create a new Null output.
|
||||
function Null.new()
|
||||
local self = {
|
||||
_producer = nil,
|
||||
obj = output_null_t(),
|
||||
}
|
||||
C.output_null_init(self.obj)
|
||||
ffi.gc(self.obj, C.output_null_destroy)
|
||||
return setmetatable(self, { __index = Null })
|
||||
ok, cls = pcall(require, "example.output.null")
|
||||
if not ok then
|
||||
error("You need to install the example module output-example\n" .. cls)
|
||||
end
|
||||
|
||||
-- Return the Log object to control logging of this instance or module.
|
||||
function Null:log()
|
||||
if self == nil then
|
||||
return C.output_null_log()
|
||||
end
|
||||
return self.obj._log
|
||||
end
|
||||
|
||||
-- Return the C functions and context for receiving objects.
|
||||
function Null:receive()
|
||||
return C.output_null_receiver(), self.obj
|
||||
end
|
||||
|
||||
-- Set the producer to get objects from.
|
||||
function Null:producer(o)
|
||||
self.obj.prod, self.obj.ctx = o:produce()
|
||||
self._producer = o
|
||||
end
|
||||
|
||||
-- Retrieve all objects from the producer, if the optional
|
||||
-- .I num
|
||||
-- is a positive number then stop after that amount of objects have been
|
||||
-- retrieved.
|
||||
function Null:run(num)
|
||||
if num == nil then
|
||||
num = -1
|
||||
end
|
||||
C.output_null_run(self.obj, num)
|
||||
end
|
||||
|
||||
-- Return the number of packets we sent into the void.
|
||||
function Null:packets()
|
||||
return tonumber(self.obj.pkts)
|
||||
end
|
||||
|
||||
return Null
|
||||
return cls
|
||||
|
|
|
@ -82,6 +82,15 @@ void output_pcap_close(output_pcap_t* self)
|
|||
}
|
||||
}
|
||||
|
||||
int output_pcap_have_errors(output_pcap_t* self)
|
||||
{
|
||||
mlassert_self();
|
||||
if (self->dumper) {
|
||||
return ferror(pcap_dump_file(self->dumper));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _receive(output_pcap_t* self, const core_object_t* obj)
|
||||
{
|
||||
struct pcap_pkthdr hdr;
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
|
||||
#ifndef __dnsjit_output_pcap_h
|
||||
#define __dnsjit_output_pcap_h
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
#include "output/pcap.hh"
|
||||
#include <dnsjit/output/pcap.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,5 +37,6 @@ void output_pcap_init(output_pcap_t* self);
|
|||
void output_pcap_destroy(output_pcap_t* self);
|
||||
int output_pcap_open(output_pcap_t* self, const char* file, int linktype, int snaplen);
|
||||
void output_pcap_close(output_pcap_t* self);
|
||||
int output_pcap_have_errors(output_pcap_t* self);
|
||||
|
||||
core_receiver_t output_pcap_receiver(output_pcap_t* self);
|
||||
|
|
|
@ -60,6 +60,10 @@ end
|
|||
-- .I linktype
|
||||
-- and
|
||||
-- .IR snaplen .
|
||||
-- Uses
|
||||
-- .B pcap_dump_open()
|
||||
-- so you can pass "-" to it to open stdout, see it's man-page for more
|
||||
-- information.
|
||||
-- Returns 0 on success.
|
||||
function Pcap:open(file, linktype, snaplen)
|
||||
return C.output_pcap_open(self.obj, file, linktype, snaplen)
|
||||
|
@ -70,6 +74,16 @@ function Pcap:close()
|
|||
C.output_pcap_close(self.obj)
|
||||
end
|
||||
|
||||
-- Return true if the underlying
|
||||
-- .I FILE*
|
||||
-- indicates that there's been an error.
|
||||
function Pcap:have_errors()
|
||||
if C.output_pcap_have_errors(self.obj) == 0 then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Return the C functions and context for receiving objects.
|
||||
function Pcap:receive()
|
||||
return C.output_pcap_receiver(self.obj), self.obj
|
||||
|
|
|
@ -18,14 +18,14 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
|
||||
#ifndef __dnsjit_output_respdiff_h
|
||||
#define __dnsjit_output_respdiff_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "output/respdiff.hh"
|
||||
#include <dnsjit/output/respdiff.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#include "core/object/payload.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
#include <dnsjit/core/object/payload.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_output_tcpcli_h
|
||||
#define __dnsjit_output_tcpcli_h
|
||||
|
||||
#include "output/tcpcli.hh"
|
||||
#include <dnsjit/output/tcpcli.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,17 +18,17 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#include "core/object/payload.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
#include <dnsjit/core/object/payload.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_output_tlscli_h
|
||||
#define __dnsjit_output_tlscli_h
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
#include "output/tlscli.hh"
|
||||
#include <dnsjit/output/tlscli.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#include "core/object/payload.h"
|
||||
#include "core/timespec.h"
|
||||
#include <dnsjit/core/log.h>
|
||||
#include <dnsjit/core/receiver.h>
|
||||
#include <dnsjit/core/producer.h>
|
||||
#include <dnsjit/core/object/payload.h>
|
||||
#include <dnsjit/core/timespec.h>
|
||||
|
||||
#ifndef __dnsjit_output_udpcli_h
|
||||
#define __dnsjit_output_udpcli_h
|
||||
|
@ -30,6 +30,6 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "output/udpcli.hh"
|
||||
#include <dnsjit/output/udpcli.hh>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
CLEANFILES = test*.log test*.trs test*.out \
|
||||
*.pcap-dist
|
||||
*.pcap-dist *.lz4-dist *.zst-dist
|
||||
|
||||
TESTS = test1.sh test2.sh test3.sh test4.sh test5.sh test6.sh test-ipsplit.sh \
|
||||
TESTS = test1.sh test2.sh test3.sh test4.sh test6.sh test-ipsplit.sh \
|
||||
test-trie.sh test-base64url.sh
|
||||
|
||||
test1.sh: dns.pcap-dist
|
||||
test1.sh: dns.pcap-dist dns.pcap.lz4-dist dns.pcap.zst-dist
|
||||
|
||||
test2.sh: dns.pcap-dist
|
||||
|
||||
|
@ -31,8 +31,6 @@ test3.sh: dns.pcap-dist
|
|||
|
||||
test4.sh: dns.pcap-dist
|
||||
|
||||
test5.sh: dns.pcap-dist
|
||||
|
||||
test6.sh: dns.pcap-dist
|
||||
|
||||
test-ipsplit.sh: pellets.pcap-dist dns.pcap-dist
|
||||
|
@ -42,6 +40,13 @@ test-trie.sh: pellets.pcap-dist dns.pcap-dist
|
|||
.pcap.pcap-dist:
|
||||
cp "$<" "$@"
|
||||
|
||||
.lz4.lz4-dist:
|
||||
cp "$<" "$@"
|
||||
|
||||
.zst.zst-dist:
|
||||
cp "$<" "$@"
|
||||
|
||||
EXTRA_DIST = $(TESTS) \
|
||||
dns.pcap pellets.pcap test_ipsplit.lua test_trie.lua test_base64url.lua \
|
||||
test1.gold test2.gold test3.gold test4.gold
|
||||
test1.gold test2.gold test3.gold test4.gold test_compressupport.lua \
|
||||
dns.pcap.lz4 dns.pcap.zst
|
||||
|
|
947
src/test/Makefile.in
Normal file
947
src/test/Makefile.in
Normal file
|
@ -0,0 +1,947 @@
|
|||
# Makefile.in generated by automake 1.16.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
# Copyright (c) 2018-2021, OARC, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of dnsjit.
|
||||
#
|
||||
# dnsjit is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# dnsjit is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = src/test
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cflags_warn_all.m4 \
|
||||
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
|
||||
$(top_srcdir)/m4/ax_compiler_vendor.m4 \
|
||||
$(top_srcdir)/m4/ax_ext.m4 \
|
||||
$(top_srcdir)/m4/ax_gcc_x86_avx_xgetbv.m4 \
|
||||
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
|
||||
$(top_srcdir)/m4/ax_prepend_flag.m4 \
|
||||
$(top_srcdir)/m4/ax_pthread.m4 \
|
||||
$(top_srcdir)/m4/ax_require_defined.m4 \
|
||||
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
|
||||
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
|
||||
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/src/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__extra_recursive_targets = gcov-recursive
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
am__tty_colors_dummy = \
|
||||
mgn= red= grn= lgn= blu= brg= std=; \
|
||||
am__color_tests=no
|
||||
am__tty_colors = { \
|
||||
$(am__tty_colors_dummy); \
|
||||
if test "X$(AM_COLOR_TESTS)" = Xno; then \
|
||||
am__color_tests=no; \
|
||||
elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
|
||||
am__color_tests=yes; \
|
||||
elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
|
||||
am__color_tests=yes; \
|
||||
fi; \
|
||||
if test $$am__color_tests = yes; then \
|
||||
red='[0;31m'; \
|
||||
grn='[0;32m'; \
|
||||
lgn='[1;32m'; \
|
||||
blu='[1;34m'; \
|
||||
mgn='[0;35m'; \
|
||||
brg='[1m'; \
|
||||
std='[m'; \
|
||||
fi; \
|
||||
}
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
am__recheck_rx = ^[ ]*:recheck:[ ]*
|
||||
am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
|
||||
am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
|
||||
# A command that, given a newline-separated list of test names on the
|
||||
# standard input, print the name of the tests that are to be re-run
|
||||
# upon "make recheck".
|
||||
am__list_recheck_tests = $(AWK) '{ \
|
||||
recheck = 1; \
|
||||
while ((rc = (getline line < ($$0 ".trs"))) != 0) \
|
||||
{ \
|
||||
if (rc < 0) \
|
||||
{ \
|
||||
if ((getline line2 < ($$0 ".log")) < 0) \
|
||||
recheck = 0; \
|
||||
break; \
|
||||
} \
|
||||
else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
|
||||
{ \
|
||||
recheck = 0; \
|
||||
break; \
|
||||
} \
|
||||
else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
}; \
|
||||
if (recheck) \
|
||||
print $$0; \
|
||||
close ($$0 ".trs"); \
|
||||
close ($$0 ".log"); \
|
||||
}'
|
||||
# A command that, given a newline-separated list of test names on the
|
||||
# standard input, create the global log from their .trs and .log files.
|
||||
am__create_global_log = $(AWK) ' \
|
||||
function fatal(msg) \
|
||||
{ \
|
||||
print "fatal: making $@: " msg | "cat >&2"; \
|
||||
exit 1; \
|
||||
} \
|
||||
function rst_section(header) \
|
||||
{ \
|
||||
print header; \
|
||||
len = length(header); \
|
||||
for (i = 1; i <= len; i = i + 1) \
|
||||
printf "="; \
|
||||
printf "\n\n"; \
|
||||
} \
|
||||
{ \
|
||||
copy_in_global_log = 1; \
|
||||
global_test_result = "RUN"; \
|
||||
while ((rc = (getline line < ($$0 ".trs"))) != 0) \
|
||||
{ \
|
||||
if (rc < 0) \
|
||||
fatal("failed to read from " $$0 ".trs"); \
|
||||
if (line ~ /$(am__global_test_result_rx)/) \
|
||||
{ \
|
||||
sub("$(am__global_test_result_rx)", "", line); \
|
||||
sub("[ ]*$$", "", line); \
|
||||
global_test_result = line; \
|
||||
} \
|
||||
else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
|
||||
copy_in_global_log = 0; \
|
||||
}; \
|
||||
if (copy_in_global_log) \
|
||||
{ \
|
||||
rst_section(global_test_result ": " $$0); \
|
||||
while ((rc = (getline line < ($$0 ".log"))) != 0) \
|
||||
{ \
|
||||
if (rc < 0) \
|
||||
fatal("failed to read from " $$0 ".log"); \
|
||||
print line; \
|
||||
}; \
|
||||
printf "\n"; \
|
||||
}; \
|
||||
close ($$0 ".trs"); \
|
||||
close ($$0 ".log"); \
|
||||
}'
|
||||
# Restructured Text title.
|
||||
am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
|
||||
# Solaris 10 'make', and several other traditional 'make' implementations,
|
||||
# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
|
||||
# by disabling -e (using the XSI extension "set +e") if it's set.
|
||||
am__sh_e_setup = case $$- in *e*) set +e;; esac
|
||||
# Default flags passed to test drivers.
|
||||
am__common_driver_flags = \
|
||||
--color-tests "$$am__color_tests" \
|
||||
--enable-hard-errors "$$am__enable_hard_errors" \
|
||||
--expect-failure "$$am__expect_failure"
|
||||
# To be inserted before the command running the test. Creates the
|
||||
# directory for the log if needed. Stores in $dir the directory
|
||||
# containing $f, in $tst the test, in $log the log. Executes the
|
||||
# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
|
||||
# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
|
||||
# will run the test scripts (or their associated LOG_COMPILER, if
|
||||
# thy have one).
|
||||
am__check_pre = \
|
||||
$(am__sh_e_setup); \
|
||||
$(am__vpath_adj_setup) $(am__vpath_adj) \
|
||||
$(am__tty_colors); \
|
||||
srcdir=$(srcdir); export srcdir; \
|
||||
case "$@" in \
|
||||
*/*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
|
||||
*) am__odir=.;; \
|
||||
esac; \
|
||||
test "x$$am__odir" = x"." || test -d "$$am__odir" \
|
||||
|| $(MKDIR_P) "$$am__odir" || exit $$?; \
|
||||
if test -f "./$$f"; then dir=./; \
|
||||
elif test -f "$$f"; then dir=; \
|
||||
else dir="$(srcdir)/"; fi; \
|
||||
tst=$$dir$$f; log='$@'; \
|
||||
if test -n '$(DISABLE_HARD_ERRORS)'; then \
|
||||
am__enable_hard_errors=no; \
|
||||
else \
|
||||
am__enable_hard_errors=yes; \
|
||||
fi; \
|
||||
case " $(XFAIL_TESTS) " in \
|
||||
*[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
|
||||
am__expect_failure=yes;; \
|
||||
*) \
|
||||
am__expect_failure=no;; \
|
||||
esac; \
|
||||
$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
|
||||
# A shell command to get the names of the tests scripts with any registered
|
||||
# extension removed (i.e., equivalently, the names of the test logs, with
|
||||
# the '.log' extension removed). The result is saved in the shell variable
|
||||
# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
|
||||
# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
|
||||
# since that might cause problem with VPATH rewrites for suffix-less tests.
|
||||
# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
|
||||
am__set_TESTS_bases = \
|
||||
bases='$(TEST_LOGS)'; \
|
||||
bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
|
||||
bases=`echo $$bases`
|
||||
RECHECK_LOGS = $(TEST_LOGS)
|
||||
AM_RECURSIVE_TARGETS = check recheck
|
||||
TEST_SUITE_LOG = test-suite.log
|
||||
TEST_EXTENSIONS = @EXEEXT@ .test
|
||||
LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
|
||||
LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
|
||||
am__set_b = \
|
||||
case '$@' in \
|
||||
*/*) \
|
||||
case '$*' in \
|
||||
*/*) b='$*';; \
|
||||
*) b=`echo '$@' | sed 's/\.log$$//'`; \
|
||||
esac;; \
|
||||
*) \
|
||||
b='$*';; \
|
||||
esac
|
||||
am__test_logs1 = $(TESTS:=.log)
|
||||
am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
|
||||
TEST_LOGS = $(am__test_logs2:.test.log=.log)
|
||||
TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
|
||||
TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
|
||||
$(TEST_LOG_FLAGS)
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/test-driver
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CPUEXT_FLAGS = @CPUEXT_FLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||
LUAJIT = @LUAJIT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PKG_CONFIG = @PKG_CONFIG@
|
||||
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SIMD_FLAGS = @SIMD_FLAGS@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
ax_pthread_config = @ax_pthread_config@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
ck_CFLAGS = @ck_CFLAGS@
|
||||
ck_LIBS = @ck_LIBS@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
liblz4_CFLAGS = @liblz4_CFLAGS@
|
||||
liblz4_LIBS = @liblz4_LIBS@
|
||||
libzstd_CFLAGS = @libzstd_CFLAGS@
|
||||
libzstd_LIBS = @libzstd_LIBS@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
luajit_CFLAGS = @luajit_CFLAGS@
|
||||
luajit_LIBS = @luajit_LIBS@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
CLEANFILES = test*.log test*.trs test*.out \
|
||||
*.pcap-dist *.lz4-dist *.zst-dist
|
||||
|
||||
TESTS = test1.sh test2.sh test3.sh test4.sh test6.sh test-ipsplit.sh \
|
||||
test-trie.sh test-base64url.sh
|
||||
|
||||
EXTRA_DIST = $(TESTS) \
|
||||
dns.pcap pellets.pcap test_ipsplit.lua test_trie.lua test_base64url.lua \
|
||||
test1.gold test2.gold test3.gold test4.gold test_compressupport.lua \
|
||||
dns.pcap.lz4 dns.pcap.zst
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .log .lz4 .lz4-dist .pcap .pcap-dist .test .test$(EXEEXT) .trs .zst .zst-dist
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/test/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign src/test/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
gcov-local:
|
||||
tags TAGS:
|
||||
|
||||
ctags CTAGS:
|
||||
|
||||
cscope cscopelist:
|
||||
|
||||
|
||||
# Recover from deleted '.trs' file; this should ensure that
|
||||
# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
|
||||
# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
|
||||
# to avoid problems with "make -n".
|
||||
.log.trs:
|
||||
rm -f $< $@
|
||||
$(MAKE) $(AM_MAKEFLAGS) $<
|
||||
|
||||
# Leading 'am--fnord' is there to ensure the list of targets does not
|
||||
# expand to empty, as could happen e.g. with make check TESTS=''.
|
||||
am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
|
||||
am--force-recheck:
|
||||
@:
|
||||
|
||||
$(TEST_SUITE_LOG): $(TEST_LOGS)
|
||||
@$(am__set_TESTS_bases); \
|
||||
am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
|
||||
redo_bases=`for i in $$bases; do \
|
||||
am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
|
||||
done`; \
|
||||
if test -n "$$redo_bases"; then \
|
||||
redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
|
||||
redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
|
||||
if $(am__make_dryrun); then :; else \
|
||||
rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
|
||||
fi; \
|
||||
fi; \
|
||||
if test -n "$$am__remaking_logs"; then \
|
||||
echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
|
||||
"recursion detected" >&2; \
|
||||
elif test -n "$$redo_logs"; then \
|
||||
am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
|
||||
fi; \
|
||||
if $(am__make_dryrun); then :; else \
|
||||
st=0; \
|
||||
errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
|
||||
for i in $$redo_bases; do \
|
||||
test -f $$i.trs && test -r $$i.trs \
|
||||
|| { echo "$$errmsg $$i.trs" >&2; st=1; }; \
|
||||
test -f $$i.log && test -r $$i.log \
|
||||
|| { echo "$$errmsg $$i.log" >&2; st=1; }; \
|
||||
done; \
|
||||
test $$st -eq 0 || exit 1; \
|
||||
fi
|
||||
@$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
|
||||
ws='[ ]'; \
|
||||
results=`for b in $$bases; do echo $$b.trs; done`; \
|
||||
test -n "$$results" || results=/dev/null; \
|
||||
all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
|
||||
pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
|
||||
fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
|
||||
skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
|
||||
xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
|
||||
xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
|
||||
error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
|
||||
if test `expr $$fail + $$xpass + $$error` -eq 0; then \
|
||||
success=true; \
|
||||
else \
|
||||
success=false; \
|
||||
fi; \
|
||||
br='==================='; br=$$br$$br$$br$$br; \
|
||||
result_count () \
|
||||
{ \
|
||||
if test x"$$1" = x"--maybe-color"; then \
|
||||
maybe_colorize=yes; \
|
||||
elif test x"$$1" = x"--no-color"; then \
|
||||
maybe_colorize=no; \
|
||||
else \
|
||||
echo "$@: invalid 'result_count' usage" >&2; exit 4; \
|
||||
fi; \
|
||||
shift; \
|
||||
desc=$$1 count=$$2; \
|
||||
if test $$maybe_colorize = yes && test $$count -gt 0; then \
|
||||
color_start=$$3 color_end=$$std; \
|
||||
else \
|
||||
color_start= color_end=; \
|
||||
fi; \
|
||||
echo "$${color_start}# $$desc $$count$${color_end}"; \
|
||||
}; \
|
||||
create_testsuite_report () \
|
||||
{ \
|
||||
result_count $$1 "TOTAL:" $$all "$$brg"; \
|
||||
result_count $$1 "PASS: " $$pass "$$grn"; \
|
||||
result_count $$1 "SKIP: " $$skip "$$blu"; \
|
||||
result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
|
||||
result_count $$1 "FAIL: " $$fail "$$red"; \
|
||||
result_count $$1 "XPASS:" $$xpass "$$red"; \
|
||||
result_count $$1 "ERROR:" $$error "$$mgn"; \
|
||||
}; \
|
||||
{ \
|
||||
echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
|
||||
$(am__rst_title); \
|
||||
create_testsuite_report --no-color; \
|
||||
echo; \
|
||||
echo ".. contents:: :depth: 2"; \
|
||||
echo; \
|
||||
for b in $$bases; do echo $$b; done \
|
||||
| $(am__create_global_log); \
|
||||
} >$(TEST_SUITE_LOG).tmp || exit 1; \
|
||||
mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
|
||||
if $$success; then \
|
||||
col="$$grn"; \
|
||||
else \
|
||||
col="$$red"; \
|
||||
test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
|
||||
fi; \
|
||||
echo "$${col}$$br$${std}"; \
|
||||
echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
|
||||
echo "$${col}$$br$${std}"; \
|
||||
create_testsuite_report --maybe-color; \
|
||||
echo "$$col$$br$$std"; \
|
||||
if $$success; then :; else \
|
||||
echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
|
||||
if test -n "$(PACKAGE_BUGREPORT)"; then \
|
||||
echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
|
||||
fi; \
|
||||
echo "$$col$$br$$std"; \
|
||||
fi; \
|
||||
$$success || exit 1
|
||||
|
||||
check-TESTS:
|
||||
@list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
|
||||
@list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
|
||||
@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
|
||||
@set +e; $(am__set_TESTS_bases); \
|
||||
log_list=`for i in $$bases; do echo $$i.log; done`; \
|
||||
trs_list=`for i in $$bases; do echo $$i.trs; done`; \
|
||||
log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
|
||||
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
|
||||
exit $$?;
|
||||
recheck: all
|
||||
@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
|
||||
@set +e; $(am__set_TESTS_bases); \
|
||||
bases=`for i in $$bases; do echo $$i; done \
|
||||
| $(am__list_recheck_tests)` || exit 1; \
|
||||
log_list=`for i in $$bases; do echo $$i.log; done`; \
|
||||
log_list=`echo $$log_list`; \
|
||||
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
|
||||
am__force_recheck=am--force-recheck \
|
||||
TEST_LOGS="$$log_list"; \
|
||||
exit $$?
|
||||
test1.sh.log: test1.sh
|
||||
@p='test1.sh'; \
|
||||
b='test1.sh'; \
|
||||
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
test2.sh.log: test2.sh
|
||||
@p='test2.sh'; \
|
||||
b='test2.sh'; \
|
||||
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
test3.sh.log: test3.sh
|
||||
@p='test3.sh'; \
|
||||
b='test3.sh'; \
|
||||
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
test4.sh.log: test4.sh
|
||||
@p='test4.sh'; \
|
||||
b='test4.sh'; \
|
||||
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
test6.sh.log: test6.sh
|
||||
@p='test6.sh'; \
|
||||
b='test6.sh'; \
|
||||
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
test-ipsplit.sh.log: test-ipsplit.sh
|
||||
@p='test-ipsplit.sh'; \
|
||||
b='test-ipsplit.sh'; \
|
||||
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
test-trie.sh.log: test-trie.sh
|
||||
@p='test-trie.sh'; \
|
||||
b='test-trie.sh'; \
|
||||
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
test-base64url.sh.log: test-base64url.sh
|
||||
@p='test-base64url.sh'; \
|
||||
b='test-base64url.sh'; \
|
||||
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
.test.log:
|
||||
@p='$<'; \
|
||||
$(am__set_b); \
|
||||
$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
|
||||
--log-file $$b.log --trs-file $$b.trs \
|
||||
$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
|
||||
"$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
@am__EXEEXT_TRUE@.test$(EXEEXT).log:
|
||||
@am__EXEEXT_TRUE@ @p='$<'; \
|
||||
@am__EXEEXT_TRUE@ $(am__set_b); \
|
||||
@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
|
||||
@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
|
||||
@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
|
||||
@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
distdir-am: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
|
||||
check: check-am
|
||||
all-am: Makefile
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
-test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
|
||||
-test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
|
||||
-test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
|
||||
|
||||
clean-generic:
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
gcov: gcov-am
|
||||
|
||||
gcov-am: gcov-local
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: check-am install-am install-strip
|
||||
|
||||
.PHONY: all all-am check check-TESTS check-am clean clean-generic \
|
||||
clean-libtool cscopelist-am ctags-am distclean \
|
||||
distclean-generic distclean-libtool distdir dvi dvi-am gcov-am \
|
||||
gcov-local html html-am info info-am install install-am \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am recheck tags-am \
|
||||
uninstall uninstall-am
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
test1.sh: dns.pcap-dist dns.pcap.lz4-dist dns.pcap.zst-dist
|
||||
|
||||
test2.sh: dns.pcap-dist
|
||||
|
||||
test3.sh: dns.pcap-dist
|
||||
|
||||
test4.sh: dns.pcap-dist
|
||||
|
||||
test6.sh: dns.pcap-dist
|
||||
|
||||
test-ipsplit.sh: pellets.pcap-dist dns.pcap-dist
|
||||
|
||||
test-trie.sh: pellets.pcap-dist dns.pcap-dist
|
||||
|
||||
.pcap.pcap-dist:
|
||||
cp "$<" "$@"
|
||||
|
||||
.lz4.lz4-dist:
|
||||
cp "$<" "$@"
|
||||
|
||||
.zst.zst-dist:
|
||||
cp "$<" "$@"
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
BIN
src/test/dns.pcap.lz4
Normal file
BIN
src/test/dns.pcap.lz4
Normal file
Binary file not shown.
BIN
src/test/dns.pcap.zst
Normal file
BIN
src/test/dns.pcap.zst
Normal file
Binary file not shown.
|
@ -19,3 +19,13 @@
|
|||
|
||||
../dnsjit "$srcdir/../../examples/dumpdns.lua" dns.pcap-dist >test1.out
|
||||
diff "$srcdir/test1.gold" test1.out
|
||||
|
||||
support=`../dnsjit "$srcdir/test_compressupport.lua"`
|
||||
if echo "$support"|grep -q lz4; then
|
||||
../dnsjit "$srcdir/../../examples/dumpdns.lua" dns.pcap.lz4-dist lz4 >test1.out
|
||||
diff "$srcdir/test1.gold" test1.out
|
||||
fi
|
||||
if echo "$support"|grep -q zstd; then
|
||||
../dnsjit "$srcdir/../../examples/dumpdns.lua" dns.pcap.zst-dist zstd >test1.out
|
||||
diff "$srcdir/test1.gold" test1.out
|
||||
fi
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
#!/bin/sh -e
|
||||
# Copyright (c) 2018-2021, OARC, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of dnsjit.
|
||||
#
|
||||
# dnsjit is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# dnsjit is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
../dnsjit "$srcdir/../../examples/test_throughput.lua" -vvvvv -t -s 1000000
|
||||
../dnsjit "$srcdir/../../examples/test_pcap_read.lua" -vvvvv dns.pcap-dist
|
||||
../dnsjit "$srcdir/../../examples/test_pcap_read.lua" -l -vvvvv dns.pcap-dist
|
||||
../dnsjit "$srcdir/../../examples/test_pcap_read.lua" -p -vvvvv dns.pcap-dist
|
||||
../dnsjit "$srcdir/../../examples/test_pcap_read.lua" -l -p -vvvvv dns.pcap-dist
|
10
src/test/test_compressupport.lua
Normal file
10
src/test/test_compressupport.lua
Normal file
|
@ -0,0 +1,10 @@
|
|||
local zpcap = require("dnsjit.input.zpcap").new()
|
||||
|
||||
zpcap:lz4()
|
||||
if zpcap:have_support() then
|
||||
print("lz4")
|
||||
end
|
||||
zpcap:zstd()
|
||||
if zpcap:have_support() then
|
||||
print("zstd")
|
||||
end
|
|
@ -18,16 +18,11 @@
|
|||
* along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/receiver.h"
|
||||
#include "core/producer.h"
|
||||
#ifndef __dnsjit_version_h
|
||||
#define __dnsjit_version_h
|
||||
|
||||
#ifndef __dnsjit_output_null_h
|
||||
#define __dnsjit_output_null_h
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "output/null.hh"
|
||||
#define DNSJIT_MAJOR_VERSION 1
|
||||
#define DNSJIT_MINOR_VERSION 2
|
||||
#define DNSJIT_PATCH_VERSION 1
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue