├── debian
├── compat
├── docs
├── source
│ └── format
├── dirs
├── rules
├── control
├── changelog
└── copyright
├── config.rpath
├── src
├── test
│ ├── test1.sh
│ └── Makefile.am
├── main.cpp
├── exceptions.h
├── raw_socket_sender.h
├── payload_file.h
├── dns_receiver_thread.h
├── packet.h
├── query.h
├── raw_socket_receiver.h
├── dns_receiver_thread.cpp
├── raw_socket_sender.cpp
├── dns_sender_thread.h
├── system_stat.h
├── dns_sender.h
├── query.cpp
├── payload_file.cpp
├── packet.cpp
├── dnsmeter.1.in
├── dns_sender_thread.cpp
├── raw_socket_receiver.cpp
├── system_stat.cpp
├── Makefile.am
└── dns_sender.cpp
├── .gitmodules
├── fmt.sh
├── .clang-format
├── autogen.sh
├── .copr
└── Makefile
├── Makefile.am
├── m4
├── dl.sh
├── ax_require_defined.m4
├── ax_append_flag.m4
├── ax_prepend_flag.m4
├── ax_compiler_vendor.m4
├── ax_cflags_warn_all.m4
└── ax_pthread.m4
├── CHANGES
├── .gitignore
├── configure.ac
├── rpm
└── dnsmeter.spec
└── README.md
/debian/compat:
--------------------------------------------------------------------------------
1 | 10
2 |
--------------------------------------------------------------------------------
/debian/docs:
--------------------------------------------------------------------------------
1 | README.md
2 |
--------------------------------------------------------------------------------
/debian/source/format:
--------------------------------------------------------------------------------
1 | 3.0 (quilt)
2 |
--------------------------------------------------------------------------------
/config.rpath:
--------------------------------------------------------------------------------
1 | src/pplib/autoconf/config.rpath
--------------------------------------------------------------------------------
/debian/dirs:
--------------------------------------------------------------------------------
1 | usr/share/man/man1
2 | usr/bin
3 |
--------------------------------------------------------------------------------
/src/test/test1.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -xe
2 |
3 | ../dnsmeter -h
4 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/pplib"]
2 | path = src/pplib
3 | url = https://github.com/DNS-OARC/pplib.git
4 |
--------------------------------------------------------------------------------
/fmt.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | clang-format-4.0 \
4 | -style=file \
5 | -i \
6 | src/*.cpp \
7 | src/*.h
8 |
--------------------------------------------------------------------------------
/src/test/Makefile.am:
--------------------------------------------------------------------------------
1 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
2 |
3 | CLEANFILES = test*.log test*.trs
4 |
5 | TESTS = test1.sh
6 |
7 | EXTRA_DIST = $(TESTS)
8 |
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | BasedOnStyle: webkit
2 | IndentWidth: 4
3 | AlignConsecutiveAssignments: true
4 | AlignConsecutiveDeclarations: true
5 | AlignOperands: true
6 | SortIncludes: false
7 |
--------------------------------------------------------------------------------
/debian/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 | # -*- makefile -*-
3 |
4 | # Uncomment this to turn on verbose mode.
5 | #export DH_VERBOSE=1
6 |
7 | %:
8 | dh $@
9 |
10 | override_dh_auto_configure:
11 | ./autogen.sh
12 | dh_auto_configure
13 |
--------------------------------------------------------------------------------
/autogen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 | # Copyright (c) 2019-2021, OARC, Inc.
3 | # Copyright (c) 2019, DENIC eG
4 | # All rights reserved.
5 | #
6 | # This file is part of dnsmeter.
7 | #
8 | # dnsmeter is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # dnsmeter is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with dnsmeter. If not, see .
20 |
21 | autoreconf --force --install --no-recursive --include=m4
22 |
--------------------------------------------------------------------------------
/.copr/Makefile:
--------------------------------------------------------------------------------
1 | top=..
2 |
3 | all: srpm
4 |
5 | prereq: $(top)/rpmbuild
6 | rpm -q git rpm-build >/dev/null || dnf -y install git rpm-build
7 |
8 | update-dist-tools: $(top)/dist-tools
9 | ( cd "$(top)/dist-tools" && git pull )
10 |
11 | $(top)/dist-tools:
12 | git clone https://github.com/jelu/dist-tools.git "$(top)/dist-tools"
13 |
14 | $(top)/rpmbuild:
15 | mkdir -p "$(top)"/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
16 |
17 | srpm: prereq update-dist-tools
18 | test -f .gitmodules && git submodule update --init || true
19 | echo "$(spec)" | grep -q "develop.spec" && auto_build_number=`date --utc +%s` message="Auto build `date --utc --iso-8601=seconds`" "$(top)/dist-tools/spec-new-changelog-entry" || true
20 | overwrite=yes nosign=yes "$(top)/dist-tools/create-source-packages" rpm
21 | cp ../*.orig.tar.gz "$(top)/rpmbuild/SOURCES/"
22 | echo "$(spec)" | grep -q "develop.spec" && rpmbuild -bs --define "%_topdir $(top)/rpmbuild" --undefine=dist rpm/*.spec || rpmbuild -bs --define "%_topdir $(top)/rpmbuild" --undefine=dist "$(spec)"
23 | cp "$(top)"/rpmbuild/SRPMS/*.src.rpm "$(outdir)"
24 |
--------------------------------------------------------------------------------
/Makefile.am:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2019-2021, OARC, Inc.
2 | # Copyright (c) 2019, DENIC eG
3 | # All rights reserved.
4 | #
5 | # This file is part of dnsmeter.
6 | #
7 | # dnsmeter is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # dnsmeter is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with dnsmeter. If not, see .
19 |
20 | ACLOCAL_AMFLAGS = -I m4
21 |
22 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in \
23 | $(srcdir)/src/config.h.in~ \
24 | $(srcdir)/configure
25 |
26 | SUBDIRS = src
27 |
28 | dist_doc_DATA = CHANGES README.md LICENSE
29 |
30 | EXTRA_DIST = m4
31 |
32 | test: check
33 |
--------------------------------------------------------------------------------
/m4/dl.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 | # Copyright (c) 2019-2021, OARC, Inc.
3 | # Copyright (c) 2019, DENIC eG
4 | # All rights reserved.
5 | #
6 | # This file is part of dnsmeter.
7 | #
8 | # dnsmeter is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # dnsmeter is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with dnsmeter. If not, see .
20 |
21 | m4_files="ax_append_flag.m4 ax_cflags_warn_all.m4 ax_compiler_vendor.m4 \
22 | ax_prepend_flag.m4 ax_pthread.m4 ax_require_defined.m4"
23 |
24 | for ax in $m4_files; do
25 | rm -f "$ax"
26 | wget -O "$ax" "http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/$ax"
27 | done
28 |
--------------------------------------------------------------------------------
/CHANGES:
--------------------------------------------------------------------------------
1 | 2021-06-02 Jerry Lundström
2 |
3 | Release 1.0.2
4 |
5 | This release fixes an issue with source port being static when only
6 | using `-q` to generate traffic from one host/IP. The source port is
7 | now randomized for every DNS query.
8 |
9 | Other changes is mainly about build system, packages and fixed issues
10 | detected by code analysis tools.
11 |
12 | 05000cc Typo, random source port
13 | 6a71707 Coverage
14 | 1c724ce SonarCloud
15 | 0776d20 Badges
16 | c274884 LGTM
17 | 5a12c61 COPR
18 | f77efed Build dependency
19 | a359b66 iconv
20 |
21 | 2019-10-07 Jerry Lundström
22 |
23 | Release 1.0.1
24 |
25 | This release fixes a few minor bugs and a dependency issue which made
26 | `dnsmeter` throw an exception when using the `-r` option.
27 |
28 | Bugfixes:
29 | - Use existing `rtt_avg`, was showing total RTT divided by number of threads
30 | - Fix an issue which missed the first 8 bytes of a text payload
31 |
32 | 72197b5 PCAP detect
33 | 665be2d RTT average
34 | 3fe7b66 pplib dependencies, RTT average
35 | e565d42 Funding
36 | 1a1ea40 README
37 |
38 | 2019-09-23 Jerry Lundström
39 |
40 | Release 1.0.0
41 |
42 | Initial release after project was moved from DENIC to DNS-OARC.
43 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.elf
9 |
10 | # Linker output
11 | *.ilk
12 | *.map
13 | *.exp
14 |
15 | # Precompiled Headers
16 | *.gch
17 | *.pch
18 |
19 | # Libraries
20 | *.lib
21 | *.a
22 | *.la
23 | *.lo
24 |
25 | # Shared objects (inc. Windows DLLs)
26 | *.dll
27 | *.so
28 | *.so.*
29 | *.dylib
30 |
31 | # Executables
32 | *.exe
33 | *.out
34 | *.app
35 | *.i*86
36 | *.x86_64
37 | *.hex
38 |
39 | # Debug files
40 | *.dSYM/
41 | *.su
42 | *.idb
43 | *.pdb
44 |
45 | # Kernel Module Compile Results
46 | *.mod*
47 | *.cmd
48 | .tmp_versions/
49 | modules.order
50 | Module.symvers
51 | Mkfile.old
52 | dkms.conf
53 |
54 | # Automake
55 | Makefile.in
56 | aclocal.m4
57 | ar-lib
58 | autom4te.cache
59 | compile
60 | config.guess
61 | config.sub
62 | configure
63 | depcomp
64 | install-sh
65 | ltmain.sh
66 | m4/libtool.m4
67 | m4/ltoptions.m4
68 | m4/ltsugar.m4
69 | m4/ltversion.m4
70 | m4/lt~obsolete.m4
71 | missing
72 | config.h.in
73 | config.h.in~
74 | test-driver
75 |
76 | # Configure
77 | Makefile
78 | config.log
79 | config.status
80 | libtool
81 | .deps
82 | src/config.h
83 | src/stamp-h1
84 | build
85 | .dirstamp
86 |
87 | # Project specific files
88 | src/dnsmeter
89 | src/dnsmeter.1
90 | src/test/test-suite.log
91 | src/test/test*.sh.log
92 | src/test/test*.sh.trs
93 | src/test/*.dist
94 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "config.h"
23 |
24 | #include "dns_sender.h"
25 |
26 | #include
27 | #include
28 | #include
29 |
30 | int main(int argc, char** argv)
31 | {
32 | res_init();
33 | // For unknown reason, res_mkquery is much slower (factor 3) when not
34 | // setting the following options:
35 | _res.options |= RES_USE_EDNS0;
36 | _res.options |= RES_USE_DNSSEC;
37 |
38 | DNSSender Sender;
39 | return Sender.main(argc, argv);
40 | }
41 |
--------------------------------------------------------------------------------
/m4/ax_require_defined.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # https://www.gnu.org/software/autoconf-archive/ax_require_defined.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_REQUIRE_DEFINED(MACRO)
8 | #
9 | # DESCRIPTION
10 | #
11 | # AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
12 | # been defined and thus are available for use. This avoids random issues
13 | # where a macro isn't expanded. Instead the configure script emits a
14 | # non-fatal:
15 | #
16 | # ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
17 | #
18 | # It's like AC_REQUIRE except it doesn't expand the required macro.
19 | #
20 | # Here's an example:
21 | #
22 | # AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
23 | #
24 | # LICENSE
25 | #
26 | # Copyright (c) 2014 Mike Frysinger
27 | #
28 | # Copying and distribution of this file, with or without modification, are
29 | # permitted in any medium without royalty provided the copyright notice
30 | # and this notice are preserved. This file is offered as-is, without any
31 | # warranty.
32 |
33 | #serial 2
34 |
35 | AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
36 | m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
37 | ])dnl AX_REQUIRE_DEFINED
38 |
--------------------------------------------------------------------------------
/src/exceptions.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include
23 |
24 | #ifndef __dnsmeter_exceptions_h
25 | #define __dnsmeter_exceptions_h
26 |
27 | PPL7EXCEPTION(MissingCommandlineParameter, Exception);
28 | PPL7EXCEPTION(InvalidCommandlineParameter, Exception);
29 | PPL7EXCEPTION(InvalidDNSQuery, Exception);
30 | PPL7EXCEPTION(UnknownRRType, Exception);
31 | PPL7EXCEPTION(BufferOverflow, Exception);
32 | PPL7EXCEPTION(UnknownDestination, Exception);
33 | PPL7EXCEPTION(InvalidQueryFile, Exception);
34 | PPL7EXCEPTION(UnsupportedIPFamily, Exception);
35 | PPL7EXCEPTION(FailedToInitializePacketfilter, Exception);
36 | PPL7EXCEPTION(KernelAccessFailed, Exception);
37 | PPL7EXCEPTION(SystemCallFailed, Exception);
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/debian/control:
--------------------------------------------------------------------------------
1 | Source: dnsmeter
2 | Section: net
3 | Priority: optional
4 | Maintainer: Jerry Lundström
5 | Build-Depends: debhelper (>= 10), build-essential, automake, autoconf,
6 | libtool, libssl-dev, libbz2-dev, libidn2-dev | libidn11-dev,
7 | zlib1g-dev, libpcap-dev, libpcre3-dev, gettext
8 | Standards-Version: 3.9.4
9 | Homepage: https://codeberg.org/DNS-OARC/dnsmeter
10 | Vcs-Git: https://codeberg.org/DNS-OARC/dnsmeter.git
11 | Vcs-Browser: https://codeberg.org/DNS-OARC/dnsmeter
12 |
13 | Package: dnsmeter
14 | Architecture: any
15 | Depends: ${shlibs:Depends}, ${misc:Depends}
16 | Description: DNS performance and infrastructure testing
17 | DNSMeter is a tool for testing performance of nameserver and/or
18 | infrastructure around it.
19 | It generates dns queries and sends them via UDP to a target nameserver
20 | and counts the answers.
21 | .
22 | Features:
23 | - payload can be given as text file or pcap file
24 | - can automatically run different load steps, which can be given as
25 | list or ranges
26 | - results per load step can be stored in CSV file
27 | - sender address can be spoofed from a given network or from pcap file,
28 | if payload is a pcap file
29 | - answers are counted, even if source address is spoofed, if answers get
30 | routed back to the load generator
31 | - roundtrip-times are measured (average, min, mix)
32 | - amount of DNSSEC queries can be given as percentage of total traffic
33 | - optimized for high amount of packets. On an Intel(R) Xeon(R) CPU E5-2430
34 | v2 @ 2.50GHz it can generate more than 900.000 packets per second
35 |
--------------------------------------------------------------------------------
/src/raw_socket_sender.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "packet.h"
23 |
24 | #include
25 |
26 | #ifndef __dnsmeter_raw_socket_sender_h
27 | #define __dnsmeter_raw_socket_sender_h
28 |
29 | class RawSocketSender {
30 | private:
31 | #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
32 | RawSocketSender& operator=(const RawSocketSender& other);
33 | RawSocketSender(RawSocketSender &&other) noexcept;
34 | RawSocketSender const & operator=(RawSocketSender &&other);
35 | #endif
36 |
37 | void* buffer;
38 | int sd;
39 |
40 | public:
41 | RawSocketSender();
42 | ~RawSocketSender();
43 | void setDestination(const ppl7::IPAddress& ip_addr, int port);
44 | ssize_t send(Packet& pkt);
45 | ppl7::SockAddr getSockAddr() const;
46 | bool socketReady();
47 | };
48 |
49 | #endif
50 |
--------------------------------------------------------------------------------
/src/payload_file.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include
23 | #include
24 |
25 | #ifndef __dnsmeter_payload_file_h
26 | #define __dnsmeter_payload_file_h
27 |
28 | class PayloadFile {
29 | private:
30 | ppl7::Mutex QueryMutex;
31 | ppluint64 validLinesInQueryFile;
32 | std::list querycache;
33 | std::list::const_iterator it;
34 | bool payloadIsPcap;
35 | bool detectPcap(ppl7::File& ff);
36 | void loadAndCompile(ppl7::File& ff);
37 | void loadAndCompilePcapFile(const ppl7::String& Filename);
38 |
39 | public:
40 | PayloadFile();
41 | void openQueryFile(const ppl7::String& Filename);
42 | const ppl7::ByteArrayPtr& getQuery();
43 | bool isPcap();
44 | };
45 |
46 | #endif
47 |
--------------------------------------------------------------------------------
/debian/changelog:
--------------------------------------------------------------------------------
1 | dnsmeter (1.0.2-1~unstable+1) unstable; urgency=low
2 |
3 | * Release 1.0.2
4 |
5 | This release fixes an issue with source port being static when only
6 | using `-q` to generate traffic from one host/IP. The source port is
7 | now randomized for every DNS query.
8 |
9 | Other changes is mainly about build system, packages and fixed issues
10 | detected by code analysis tools.
11 |
12 | 05000cc Typo, random source port
13 | 6a71707 Coverage
14 | 1c724ce SonarCloud
15 | 0776d20 Badges
16 | c274884 LGTM
17 | 5a12c61 COPR
18 | f77efed Build dependency
19 | a359b66 iconv
20 |
21 | -- Jerry Lundström Wed, 02 Jun 2021 09:27:07 +0200
22 |
23 | dnsmeter (1.0.1-1~unstable+1) unstable; urgency=low
24 |
25 | * Release 1.0.1
26 |
27 | This release fixes a few minor bugs and a dependency issue which made
28 | `dnsmeter` throw an exception when using the `-r` option.
29 |
30 | Bugfixes:
31 | - Use existing `rtt_avg`, was showing total RTT divided by number of threads
32 | - Fix an issue which missed the first 8 bytes of a text payload
33 |
34 | 72197b5 PCAP detect
35 | 665be2d RTT average
36 | 3fe7b66 pplib dependencies, RTT average
37 | e565d42 Funding
38 | 1a1ea40 README
39 |
40 | -- Jerry Lundström Mon, 07 Oct 2019 16:31:06 +0200
41 |
42 | dnsmeter (1.0.0-1~unstable+1) unstable; urgency=low
43 |
44 | * Release 1.0.0
45 |
46 | -- Jerry Lundström Mon, 23 Sep 2019 15:09:21 +0200
47 |
48 | dnsmeter (0.9.0-1~unstable+1) unstable; urgency=low
49 |
50 | * First package release
51 |
52 | -- Jerry Lundström Wed, 18 Sep 2019 17:19:16 +0200
53 |
--------------------------------------------------------------------------------
/m4/ax_append_flag.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # https://www.gnu.org/software/autoconf-archive/ax_append_flag.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
8 | #
9 | # DESCRIPTION
10 | #
11 | # FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
12 | # added in between.
13 | #
14 | # If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
15 | # CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
16 | # FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
17 | # FLAG.
18 | #
19 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
20 | #
21 | # LICENSE
22 | #
23 | # Copyright (c) 2008 Guido U. Draheim
24 | # Copyright (c) 2011 Maarten Bosmans
25 | #
26 | # Copying and distribution of this file, with or without modification, are
27 | # permitted in any medium without royalty provided the copyright notice
28 | # and this notice are preserved. This file is offered as-is, without any
29 | # warranty.
30 |
31 | #serial 8
32 |
33 | AC_DEFUN([AX_APPEND_FLAG],
34 | [dnl
35 | AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
36 | AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
37 | AS_VAR_SET_IF(FLAGS,[
38 | AS_CASE([" AS_VAR_GET(FLAGS) "],
39 | [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
40 | [
41 | AS_VAR_APPEND(FLAGS,[" $1"])
42 | AC_RUN_LOG([: FLAGS="$FLAGS"])
43 | ])
44 | ],
45 | [
46 | AS_VAR_SET(FLAGS,[$1])
47 | AC_RUN_LOG([: FLAGS="$FLAGS"])
48 | ])
49 | AS_VAR_POPDEF([FLAGS])dnl
50 | ])dnl AX_APPEND_FLAG
51 |
--------------------------------------------------------------------------------
/m4/ax_prepend_flag.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # https://www.gnu.org/software/autoconf-archive/ax_prepend_flag.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_PREPEND_FLAG(FLAG, [FLAGS-VARIABLE])
8 | #
9 | # DESCRIPTION
10 | #
11 | # FLAG is added to the front of the FLAGS-VARIABLE shell variable, with a
12 | # space added in between.
13 | #
14 | # If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
15 | # CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
16 | # FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
17 | # FLAG.
18 | #
19 | # NOTE: Implementation based on AX_APPEND_FLAG.
20 | #
21 | # LICENSE
22 | #
23 | # Copyright (c) 2008 Guido U. Draheim
24 | # Copyright (c) 2011 Maarten Bosmans
25 | # Copyright (c) 2018 John Zaitseff
26 | #
27 | # Copying and distribution of this file, with or without modification, are
28 | # permitted in any medium without royalty provided the copyright notice
29 | # and this notice are preserved. This file is offered as-is, without any
30 | # warranty.
31 |
32 | #serial 2
33 |
34 | AC_DEFUN([AX_PREPEND_FLAG],
35 | [dnl
36 | AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
37 | AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
38 | AS_VAR_SET_IF(FLAGS,[
39 | AS_CASE([" AS_VAR_GET(FLAGS) "],
40 | [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
41 | [
42 | FLAGS="$1 $FLAGS"
43 | AC_RUN_LOG([: FLAGS="$FLAGS"])
44 | ])
45 | ],
46 | [
47 | AS_VAR_SET(FLAGS,[$1])
48 | AC_RUN_LOG([: FLAGS="$FLAGS"])
49 | ])
50 | AS_VAR_POPDEF([FLAGS])dnl
51 | ])dnl AX_PREPEND_FLAG
52 |
--------------------------------------------------------------------------------
/src/dns_receiver_thread.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "raw_socket_receiver.h"
23 |
24 | #include
25 | #include
26 |
27 | #ifndef __dnsmeter_dns_receiver_thread_h
28 | #define __dnsmeter_dns_receiver_thread_h
29 |
30 | class DNSReceiverThread : public ppl7::Thread {
31 | private:
32 | RawSocketReceiver Socket;
33 | RawSocketReceiver::Counter counter;
34 |
35 | public:
36 | DNSReceiverThread();
37 | ~DNSReceiverThread();
38 | void setInterface(const ppl7::String& Device);
39 | void setSource(const ppl7::IPAddress& ip, int port);
40 | void run();
41 |
42 | ppluint64 getPacketsReceived() const;
43 | ppluint64 getBytesReceived() const;
44 |
45 | double getDuration() const;
46 | double getRoundTripTimeAverage() const;
47 | double getRoundTripTimeMin() const;
48 | double getRoundTripTimeMax() const;
49 | const RawSocketReceiver::Counter& getCounter() const;
50 | };
51 |
52 | #endif
53 |
--------------------------------------------------------------------------------
/src/packet.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include
23 | #include
24 |
25 | #ifndef __dnsmeter_packet_h
26 | #define __dnsmeter_packet_h
27 |
28 | class Packet {
29 | private:
30 | #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
31 | Packet& operator=(const Packet& other);
32 | Packet(Packet &&other) noexcept;
33 | Packet const & operator=(Packet &&other);
34 | #endif
35 |
36 | unsigned char* buffer;
37 | int buffersize;
38 | int payload_size;
39 | bool chksum_valid;
40 |
41 | void updateChecksums();
42 |
43 | public:
44 | Packet();
45 | ~Packet();
46 | void setSource(const ppl7::IPAddress& ip_addr, int port);
47 | void setDestination(const ppl7::IPAddress& ip_addr, int port);
48 | void setPayload(const void* payload, size_t size);
49 | void setPayloadDNSQuery(const ppl7::String& query, bool dnssec = false);
50 | void setDnsId(unsigned short id);
51 | void setIpId(unsigned short id);
52 |
53 | void randomSourceIP(const ppl7::IPNetwork& net);
54 | void randomSourceIP(unsigned int start, unsigned int size);
55 | void randomSourcePort();
56 | void useSourceFromPcap(const char* pkt, size_t size);
57 |
58 | size_t size() const;
59 | unsigned char* ptr();
60 | };
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/src/query.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include
23 |
24 | #ifndef __dnsmeter_query_h
25 | #define __dnsmeter_query_h
26 |
27 | struct DNS_HEADER {
28 | unsigned short id; // identification number
29 |
30 | unsigned char rd : 1; // recursion desired
31 | unsigned char tc : 1; // truncated message
32 | unsigned char aa : 1; // authoritive answer
33 | unsigned char opcode : 4; // purpose of message
34 | unsigned char qr : 1; // query/response flag
35 |
36 | unsigned char rcode : 4; // response code
37 | unsigned char cd : 1; // checking disabled
38 | unsigned char ad : 1; // authenticated data
39 | unsigned char z : 1; // its z! reserved
40 | unsigned char ra : 1; // recursion available
41 |
42 | unsigned short q_count; // number of question entries
43 | unsigned short ans_count; // number of answer entries
44 | unsigned short auth_count; // number of authority entries
45 | unsigned short add_count; // number of resource entries
46 | };
47 |
48 | int MakeQuery(const ppl7::String& query, unsigned char* buffer, size_t buffersize, bool dnssec = false, int udp_payload_size = 4096);
49 | int AddDnssecToQuery(unsigned char* buffer, size_t buffersize, int querysize, int udp_payload_size = 4096);
50 | unsigned short getQueryTimestamp();
51 | double getQueryRTT(unsigned short start);
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/src/raw_socket_receiver.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include
23 | #include
24 |
25 | #ifndef __dnsmeter_raw_socket_receiver_h
26 | #define __dnsmeter_raw_socket_receiver_h
27 |
28 | class RawSocketReceiver {
29 | private:
30 | #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
31 | RawSocketReceiver& operator=(const RawSocketReceiver& other);
32 | RawSocketReceiver(RawSocketReceiver &&other) noexcept;
33 | RawSocketReceiver const & operator=(RawSocketReceiver &&other);
34 | #endif
35 |
36 | ppl7::IPAddress SourceIP;
37 | unsigned char* buffer;
38 | int buflen;
39 | int sd;
40 | unsigned short SourcePort;
41 | #ifdef __FreeBSD__
42 | bool useZeroCopyBuffer;
43 | #endif
44 |
45 | public:
46 | class Counter {
47 | public:
48 | Counter();
49 | void clear();
50 | ppluint64 num_pkgs;
51 | ppluint64 bytes_rcv;
52 | ppluint64 rcodes[16];
53 | ppluint64 truncated;
54 | double rtt_total, rtt_min, rtt_max;
55 | };
56 |
57 | RawSocketReceiver();
58 | ~RawSocketReceiver();
59 | void initInterface(const ppl7::String& Device);
60 | bool socketReady();
61 | void setSource(const ppl7::IPAddress& ip_addr, int port);
62 | void receive(Counter& counter);
63 | };
64 |
65 | #endif
66 |
--------------------------------------------------------------------------------
/src/dns_receiver_thread.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "config.h"
23 |
24 | #include "dns_receiver_thread.h"
25 |
26 | DNSReceiverThread::DNSReceiverThread()
27 | {
28 | }
29 |
30 | DNSReceiverThread::~DNSReceiverThread()
31 | {
32 | }
33 |
34 | void DNSReceiverThread::setInterface(const ppl7::String& Device)
35 | {
36 | Socket.initInterface(Device);
37 | }
38 |
39 | void DNSReceiverThread::setSource(const ppl7::IPAddress& ip, int port)
40 | {
41 | Socket.setSource(ip, port);
42 | }
43 |
44 | void DNSReceiverThread::run()
45 | {
46 | counter.clear();
47 | while (1) {
48 | if (Socket.socketReady())
49 | Socket.receive(counter);
50 | if (this->threadShouldStop())
51 | break;
52 | }
53 | }
54 |
55 | ppluint64 DNSReceiverThread::getPacketsReceived() const
56 | {
57 | return counter.num_pkgs;
58 | }
59 |
60 | ppluint64 DNSReceiverThread::getBytesReceived() const
61 | {
62 | return counter.bytes_rcv;
63 | }
64 |
65 | double DNSReceiverThread::getDuration() const
66 | {
67 | return counter.rtt_total;
68 | }
69 |
70 | double DNSReceiverThread::getRoundTripTimeAverage() const
71 | {
72 | if (counter.num_pkgs)
73 | return counter.rtt_total / counter.num_pkgs; //NOSONAR
74 | return 0.0f;
75 | }
76 |
77 | double DNSReceiverThread::getRoundTripTimeMin() const
78 | {
79 | return counter.rtt_min;
80 | }
81 |
82 | double DNSReceiverThread::getRoundTripTimeMax() const
83 | {
84 | return counter.rtt_max;
85 | }
86 |
87 | const RawSocketReceiver::Counter& DNSReceiverThread::getCounter() const
88 | {
89 | return counter;
90 | }
91 |
--------------------------------------------------------------------------------
/src/raw_socket_sender.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "config.h"
23 |
24 | #include "raw_socket_sender.h"
25 | #include "exceptions.h"
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | RawSocketSender::RawSocketSender()
33 | {
34 | buffer = calloc(1, sizeof(struct sockaddr_in));
35 | if (!buffer)
36 | throw ppl7::OutOfMemoryException();
37 | struct sockaddr_in* dest = (struct sockaddr_in*)buffer;
38 | dest->sin_addr.s_addr = -1;
39 | if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) {
40 | free(buffer);
41 | ppl7::throwExceptionFromErrno(errno, "Could not create RawSocket");
42 | }
43 | unsigned int set = 1;
44 | if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, &set, sizeof(set)) < 0) {
45 | close(sd);
46 | free(buffer);
47 | ppl7::throwExceptionFromErrno(errno, "Could not set socket option IP_HDRINCL");
48 | }
49 | }
50 |
51 | RawSocketSender::~RawSocketSender()
52 | {
53 | close(sd);
54 | free(buffer);
55 | }
56 |
57 | void RawSocketSender::setDestination(const ppl7::IPAddress& ip_addr, int port)
58 | {
59 | if (ip_addr.family() != ppl7::IPAddress::IPv4)
60 | throw UnsupportedIPFamily("Only IPv4 is supported");
61 | ip_addr.toSockAddr(buffer, sizeof(struct sockaddr_in));
62 | ((struct sockaddr_in*)buffer)->sin_port = htons(port);
63 | }
64 |
65 | ssize_t RawSocketSender::send(Packet& pkt)
66 | {
67 | struct sockaddr_in* dest = (struct sockaddr_in*)buffer;
68 | if (dest->sin_addr.s_addr == (unsigned int)-1)
69 | throw UnknownDestination();
70 | return sendto(sd, pkt.ptr(), pkt.size(), 0,
71 | (const struct sockaddr*)dest, sizeof(struct sockaddr_in));
72 | }
73 |
74 | ppl7::SockAddr RawSocketSender::getSockAddr() const
75 | {
76 | return ppl7::SockAddr(buffer, sizeof(struct sockaddr_in));
77 | }
78 |
79 | bool RawSocketSender::socketReady()
80 | {
81 | fd_set wset;
82 | struct timeval timeout;
83 | timeout.tv_sec = 0;
84 | timeout.tv_usec = 100;
85 | FD_ZERO(&wset);
86 | FD_SET(sd, &wset); // Wir wollen nur prüfen, ob wir schreiben können
87 | int ret = select(sd + 1, NULL, &wset, NULL, &timeout);
88 | if (ret < 0)
89 | return false;
90 | if (FD_ISSET(sd, &wset)) {
91 | return true;
92 | }
93 | return false;
94 | }
95 |
--------------------------------------------------------------------------------
/src/dns_sender_thread.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "raw_socket_sender.h"
23 | #include "payload_file.h"
24 |
25 | #include
26 |
27 | #ifndef __dnsmeter_dns_sender_thread_h
28 | #define __dnsmeter_dns_sender_thread_h
29 |
30 | class DNSSenderThread : public ppl7::Thread {
31 | private:
32 | #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
33 | DNSSenderThread& operator=(const DNSSenderThread& other);
34 | DNSSenderThread(DNSSenderThread &&other) noexcept;
35 | DNSSenderThread const & operator=(DNSSenderThread &&other);
36 | #endif
37 |
38 | RawSocketSender Socket;
39 | Packet pkt;
40 |
41 | ppl7::IPAddress destination;
42 | ppl7::IPAddress sourceip;
43 | ppl7::IPNetwork sourcenet;
44 |
45 | PayloadFile* payload;
46 | unsigned char* buffer;
47 | ppluint64 queryrate;
48 | ppluint64 counter_packets_send, errors, counter_0bytes;
49 | ppluint64 counter_bytes_send;
50 | ppluint64 counter_errorcodes[255];
51 |
52 | unsigned int spoofing_net_start;
53 | unsigned int spoofing_net_size;
54 |
55 | int runtime;
56 | int timeout;
57 | int DnssecRate;
58 | int dnsseccounter;
59 | double Timeslice;
60 |
61 | double duration;
62 | bool spoofingEnabled;
63 | bool verbose;
64 | bool payloadIsPcap;
65 | bool spoofingFromPcap;
66 |
67 | void sendPacket();
68 | void waitForTimeout();
69 | bool socketReady();
70 |
71 | void runWithoutRateLimit();
72 | void runWithRateLimit();
73 |
74 | public:
75 | DNSSenderThread();
76 | ~DNSSenderThread();
77 | void setDestination(const ppl7::IPAddress& ip, int port);
78 | void setSourceIP(const ppl7::IPAddress& ip);
79 | void setSourceNet(const ppl7::IPNetwork& net);
80 | void setSourcePcap();
81 | void setRandomSource(const ppl7::IPNetwork& net);
82 | void setRuntime(int seconds);
83 | void setTimeout(int seconds);
84 | void setDNSSECRate(int rate);
85 | void setQueryRate(ppluint64 qps);
86 | void setTimeslice(float ms);
87 | void setVerbose(bool verbose);
88 | void setPayload(PayloadFile& payload);
89 | void run();
90 | ppluint64 getPacketsSend() const;
91 | ppluint64 getBytesSend() const;
92 | ppluint64 getErrors() const;
93 | ppluint64 getCounter0Bytes() const;
94 | ppluint64 getCounterErrorCode(int err) const;
95 | };
96 |
97 | #endif
98 |
--------------------------------------------------------------------------------
/configure.ac:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2019-2021, OARC, Inc.
2 | # Copyright (c) 2019, DENIC eG
3 | # All rights reserved.
4 | #
5 | # This file is part of dnsmeter.
6 | #
7 | # dnsmeter is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # dnsmeter is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with dnsmeter. If not, see .
19 |
20 | AC_PREREQ(2.69)
21 | AC_INIT([dnsmeter], [1.0.2], [admin@dns-oarc.net], [dnsmeter], [https://codeberg.org/DNS-OARC/dnsmeter/issues])
22 | AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
23 | AC_CONFIG_SRCDIR([src/main.cpp])
24 | AC_CONFIG_HEADER([src/config.h])
25 | AC_CONFIG_MACRO_DIR([m4])
26 |
27 | # Checks for programs.
28 | AC_PROG_CXX
29 | AC_CANONICAL_HOST
30 | LT_INIT([disable-static])
31 |
32 | # Check --enable-warn-all
33 | AC_ARG_ENABLE([warn-all], [AS_HELP_STRING([--enable-warn-all], [Enable all compiler warnings])], [AX_CFLAGS_WARN_ALL()])
34 |
35 | # Check --with-extra-cflags
36 | AC_ARG_WITH([extra-cflags], [AS_HELP_STRING([--with-extra-cflags=CFLAGS], [Add extra CFLAGS/CXXFLAGS])], [
37 | AC_MSG_NOTICE([appending extra CFLAGS/CXXFLAGS... $withval])
38 | AS_VAR_APPEND(CFLAGS, [" $withval"])
39 | AS_VAR_APPEND(CXXFLAGS, [" $withval"])
40 | ])
41 |
42 | # Check --with-extra-ldflags
43 | AC_ARG_WITH([extra-ldflags], [AS_HELP_STRING([--with-extra-ldflags=LDFLAGS], [Add extra LDFLAGS])], [
44 | AC_MSG_NOTICE([appending extra LDFLAGS... $withval])
45 | AS_VAR_APPEND(LDFLAGS, [" $withval"])
46 | ])
47 |
48 | # Check --enable-gcov
49 | AC_ARG_ENABLE([gcov], [AS_HELP_STRING([--enable-gcov], [Enable coverage testing])], [
50 | coverage_cxxflags="--coverage -g -O0 -fno-inline -fno-inline-small-functions -fno-default-inline"
51 | AC_MSG_NOTICE([enabling coverage testing... $coverage_cxxflags])
52 | AS_VAR_APPEND(CXXFLAGS, [" $coverage_cxxflags"])
53 | ])
54 | AM_CONDITIONAL([ENABLE_GCOV], [test "x$enable_gcov" != "xno"])
55 | AM_EXTRA_RECURSIVE_TARGETS([gcov])
56 |
57 | # Checks for support.
58 | AX_PTHREAD
59 | AC_CHECK_LIB([pcap], [pcap_open_live], [], [AC_MSG_ERROR([libpcap not found])])
60 | AC_CHECK_LIB([m], [sqrt])
61 | AC_CHECK_LIB([bind], [ns_initparse], [], [AC_CHECK_LIB([bind], [__ns_initparse])])
62 | AC_CHECK_LIB([resolv], [res_mkquery], [], [
63 | AC_CHECK_LIB([resolv], [__res_mkquery], [], [
64 | AC_CHECK_LIB([resolv], [res_9_mkquery])
65 | ])
66 | ])
67 | AC_CHECK_LIB([idn], [idna_to_ascii_4z])
68 | AC_CHECK_LIB([idn2], [idn2_to_ascii_4z])
69 | AC_CHECK_LIB([pcre], [pcre_exec])
70 |
71 | sinclude(src/pplib/autoconf/iconv.m4)
72 |
73 | # Check for OS specific libraries
74 | case "$host_os" in
75 | freebsd*)
76 | AC_CHECK_LIB([kvm], [kvm_open])
77 | AM_ICONV
78 | ICONV_CFLAGS="$INCICONV"
79 | ICONV_LIBS="$LIBICONV"
80 | AC_SUBST(ICONV_CFLAGS)
81 | AC_SUBST(ICONV_LIBS)
82 | ;;
83 | esac
84 |
85 | # Output Makefiles
86 | AC_CONFIG_FILES([
87 | Makefile
88 | src/Makefile
89 | src/test/Makefile
90 | ])
91 | AC_OUTPUT
92 |
--------------------------------------------------------------------------------
/src/system_stat.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include
23 |
24 | #ifndef __dnsmeter_system_stat_h
25 | #define __dnsmeter_system_stat_h
26 |
27 | class SystemStat {
28 | public:
29 | class Network {
30 | public:
31 | unsigned long bytes;
32 | unsigned long packets;
33 | unsigned long errs;
34 | unsigned long drop;
35 | Network()
36 | {
37 | bytes = packets = errs = drop = 0;
38 | }
39 | Network(unsigned long bytes, unsigned long packets, unsigned long errs, unsigned long drop)
40 | {
41 | this->bytes = bytes;
42 | this->packets = packets;
43 | this->errs = errs;
44 | this->drop = drop;
45 | }
46 | void clear()
47 | {
48 | bytes = packets = errs = drop = 0;
49 | }
50 | void print()
51 | {
52 | printf("Network bytes: %lu, packets: %lu, errs: %lu, drop: %lu\n",
53 | bytes, packets, errs, drop);
54 | }
55 |
56 | static Network getDelta(const Network& sample1, const Network& sample2);
57 | };
58 |
59 | class Cpu {
60 | public:
61 | Cpu()
62 | {
63 | user = nice = system = idle = iowait = 0;
64 | }
65 | int user;
66 | int nice;
67 | int system;
68 | int idle;
69 | int iowait;
70 |
71 | static double getUsage(const SystemStat::Cpu& sample1, const SystemStat::Cpu& sample2);
72 | };
73 |
74 | class Sysinfo {
75 | public:
76 | Sysinfo()
77 | {
78 | uptime = freeswap = totalswap = freeram = bufferram = totalram = sharedram = 0;
79 | procs = 0;
80 | }
81 | long uptime;
82 | long freeswap;
83 | long totalswap;
84 | long freeram;
85 | long bufferram;
86 | long totalram;
87 | long sharedram;
88 | int procs;
89 | };
90 |
91 | class Interface {
92 | public:
93 | ppl7::String Name;
94 | Network receive;
95 | Network transmit;
96 | };
97 |
98 | double sampleTime;
99 |
100 | Cpu cpu;
101 | Sysinfo sysinfo;
102 | Interface net_total;
103 | std::map interfaces;
104 |
105 | void exportToArray(ppl7::AssocArray& data) const;
106 | void importFromArray(const ppl7::AssocArray& data);
107 | void print() const;
108 | };
109 |
110 | void sampleSensorData(SystemStat& stat);
111 |
112 | #endif
113 |
--------------------------------------------------------------------------------
/rpm/dnsmeter.spec:
--------------------------------------------------------------------------------
1 | Name: dnsmeter
2 | Version: 1.0.2
3 | Release: 1%{?dist}
4 | Summary: DNS performance and infrastructure testing
5 | Group: Productivity/Networking/DNS/Utilities
6 |
7 | License: GPL-3.0
8 | URL: https://www.dns-oarc.net/tools/dnsmeter
9 | # Source needs to be generated by dist-tools/create-source-packages, see
10 | # https://github.com/jelu/dist-tools
11 | Source0: %{name}_%{version}.orig.tar.gz
12 |
13 | BuildRequires: autoconf
14 | BuildRequires: automake
15 | BuildRequires: libtool
16 | BuildRequires: gcc-c++
17 | BuildRequires: bind-devel
18 | BuildRequires: openssl-devel
19 | %if 0%{?suse_version} || 0%{?sle_version}
20 | BuildRequires: libbz2-devel
21 | %else
22 | BuildRequires: bzip2-devel
23 | %endif
24 | BuildRequires: libidn2-devel
25 | BuildRequires: zlib-devel
26 | BuildRequires: libpcap-devel
27 | BuildRequires: pcre-devel
28 | BuildRequires: gettext-devel
29 |
30 | %description
31 | DNSMeter is a tool for testing performance of nameserver and/or
32 | infrastructure around it.
33 | It generates dns queries and sends them via UDP to a target nameserver
34 | and counts the answers.
35 |
36 | Features:
37 | - payload can be given as text file or pcap file
38 | - can automatically run different load steps, which can be given as
39 | list or ranges
40 | - results per load step can be stored in CSV file
41 | - sender address can be spoofed from a given network or from pcap file,
42 | if payload is a pcap file
43 | - answers are counted, even if source address is spoofed, if answers get
44 | routed back to the load generator
45 | - roundtrip-times are measured (average, min, mix)
46 | - amount of DNSSEC queries can be given as percentage of total traffic
47 | - optimized for high amount of packets. On an Intel(R) Xeon(R) CPU E5-2430
48 | v2 @ 2.50GHz it can generate more than 900.000 packets per second
49 |
50 |
51 | %prep
52 | %setup -q -n %{name}_%{version}
53 |
54 |
55 | %build
56 | sh autogen.sh
57 | %configure
58 | %make_build
59 |
60 |
61 | %install
62 | %make_install
63 |
64 |
65 | %check
66 | true
67 |
68 |
69 | %files
70 | %{_bindir}/dnsmeter
71 | %{_datadir}/doc/*
72 | %{_mandir}/man1/*
73 |
74 |
75 | %changelog
76 | * Wed Jun 02 2021 Jerry Lundström 1.0.2-1
77 | - Release 1.0.2
78 | * This release fixes an issue with source port being static when only
79 | using `-q` to generate traffic from one host/IP. The source port is
80 | now randomized for every DNS query.
81 | * Other changes is mainly about build system, packages and fixed issues
82 | detected by code analysis tools.
83 | * Commits:
84 | 05000cc Typo, random source port
85 | 6a71707 Coverage
86 | 1c724ce SonarCloud
87 | 0776d20 Badges
88 | c274884 LGTM
89 | 5a12c61 COPR
90 | f77efed Build dependency
91 | a359b66 iconv
92 | * Mon Oct 07 2019 Jerry Lundström 1.0.1-1
93 | - Release 1.0.1
94 | * This release fixes a few minor bugs and a dependency issue which made
95 | `dnsmeter` throw an exception when using the `-r` option.
96 | * Bugfixes:
97 | - Use existing `rtt_avg`, was showing total RTT divided by number of threads
98 | - Fix an issue which missed the first 8 bytes of a text payload
99 | * Commits:
100 | 72197b5 PCAP detect
101 | 665be2d RTT average
102 | 3fe7b66 pplib dependencies, RTT average
103 | e565d42 Funding
104 | 1a1ea40 README
105 | * Mon Sep 23 2019 Jerry Lundström 1.0.0-1
106 | - Release 1.0.0
107 | * Wed Sep 18 2019 Jerry Lundström 0.9.0-1
108 | - First package release
109 |
--------------------------------------------------------------------------------
/src/dns_sender.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "dns_receiver_thread.h"
23 | #include "payload_file.h"
24 | #include "system_stat.h"
25 |
26 | #include
27 |
28 | #ifndef __dnsmeter_dns_sender_h
29 | #define __dnsmeter_dns_sender_h
30 |
31 | class DNSSender {
32 | private:
33 | #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
34 | DNSSender& operator=(const DNSSender& other);
35 | DNSSender(DNSSender &&other) noexcept;
36 | DNSSender const & operator=(DNSSender &&other);
37 | #endif
38 |
39 | public:
40 | class Results {
41 | public:
42 | int queryrate;
43 | ppluint64 counter_send;
44 | ppluint64 counter_received;
45 | ppluint64 bytes_send;
46 | ppluint64 bytes_received;
47 | ppluint64 counter_errors;
48 | ppluint64 packages_lost;
49 | ppluint64 counter_0bytes;
50 | ppluint64 counter_errorcodes[255];
51 | ppluint64 rcodes[16];
52 | ppluint64 truncated;
53 | double rtt_total;
54 | double rtt_avg;
55 | double rtt_min;
56 | double rtt_max;
57 | Results();
58 | void clear();
59 | };
60 |
61 | private:
62 | ppl7::ThreadPool threadpool;
63 | ppl7::IPAddress TargetIP;
64 | ppl7::IPAddress SourceIP;
65 | ppl7::IPNetwork SourceNet;
66 | ppl7::String CSVFileName;
67 | ppl7::String QueryFilename;
68 | ppl7::File CSVFile;
69 | ppl7::Array rates;
70 | ppl7::String InterfaceName;
71 | PayloadFile payload;
72 | DNSReceiverThread* Receiver;
73 | DNSSender::Results vis_prev_results;
74 | SystemStat sys1, sys2;
75 |
76 | int TargetPort;
77 | int Runtime;
78 | int Timeout;
79 | int ThreadCount;
80 | int DnssecRate;
81 | float Timeslices;
82 | bool ignoreResponses;
83 | bool spoofingEnabled;
84 | bool spoofFromPcap;
85 |
86 | void openCSVFile(const ppl7::String& Filename);
87 | void run(int queryrate);
88 | void presentResults(const DNSSender::Results& result);
89 | void saveResultsToCsv(const DNSSender::Results& result);
90 | void prepareThreads();
91 | void getResults(DNSSender::Results& result);
92 | ppl7::Array getQueryRates(const ppl7::String& QueryRates);
93 | void readSourceIPList(const ppl7::String& filename);
94 |
95 | void getTarget(int argc, char** argv);
96 | void getSource(int argc, char** argv);
97 | int getParameter(int argc, char** argv);
98 | int openFiles();
99 | void calcTimeslice(int queryrate);
100 |
101 | void showCurrentStats(ppl7::ppl_time_t start_time);
102 |
103 | public:
104 | DNSSender();
105 | ~DNSSender();
106 | void help();
107 | int main(int argc, char** argv);
108 | };
109 |
110 | DNSSender::Results operator-(const DNSSender::Results& first, const DNSSender::Results& second);
111 |
112 | #endif
113 |
--------------------------------------------------------------------------------
/src/query.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "config.h"
23 |
24 | #include "query.h"
25 | #include "exceptions.h"
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | static const char* rr_types[] = {
34 | "A", "AAAA", "MX", "NS", "DS", "DNSKEY", "TXT", "SOA", "NAPTR", "RRSIG",
35 | "NSEC", "NSEC3", "NSEC3PARAM", "PTR", "SRV",
36 | "CNAME", "TSIG", "*", "ANY", "AXFR", "IXFR",
37 | "SPF", "A6", "HINFO", "WKS", "NULL",
38 | NULL
39 | };
40 |
41 | static int rr_code[] = {
42 | 1, 28, 15, 2, 43, 48, 16, 6, 35, 46,
43 | 47, 50, 51, 12, 33,
44 | 5, 250, 255, 255, 252, 251,
45 | 99, 38, 13, 11, 10,
46 | 0
47 | };
48 |
49 | #pragma pack(push) /* push current alignment to stack */
50 | #pragma pack(1) /* set alignment to 1 byte boundary */
51 | struct DNS_OPT {
52 | unsigned char name;
53 | unsigned short type;
54 | unsigned short udp_payload_size;
55 | unsigned char extended_rcode;
56 | unsigned char edns0_version;
57 | unsigned short z;
58 | unsigned short data_length;
59 | };
60 | #pragma pack(pop) /* restore original alignment from stack */
61 |
62 | int MakeQuery(const ppl7::String& query, unsigned char* buffer, size_t buffersize, bool dnssec, int udp_payload_size)
63 | {
64 | ppl7::Array tok(query, " ");
65 | if (tok.size() != 2)
66 | throw InvalidDNSQuery(query);
67 | ppl7::String Type = tok[1].toUpperCase();
68 |
69 | int t = 0;
70 | const char* str = Type.c_str();
71 | while (rr_types[t] != NULL) {
72 | if (!strcmp(str, rr_types[t])) {
73 | int bytes = res_mkquery(QUERY,
74 | (const char*)tok[0],
75 | C_IN,
76 | rr_code[t],
77 | NULL, 0, NULL, buffer, (int)buffersize);
78 | if (bytes < 0)
79 | throw InvalidDNSQuery("%s", hstrerror(h_errno));
80 | if (!dnssec)
81 | return bytes;
82 | return AddDnssecToQuery(buffer, buffersize, bytes, udp_payload_size);
83 | }
84 | t++;
85 | }
86 | throw UnknownRRType(tok[1]);
87 | }
88 |
89 | int AddDnssecToQuery(unsigned char* buffer, size_t buffersize, int querysize, int udp_payload_size)
90 | {
91 | DNS_HEADER* dns = (DNS_HEADER*)buffer;
92 | dns->ad = 1;
93 | dns->add_count = htons(1);
94 | DNS_OPT* opt = (DNS_OPT*)(buffer + querysize);
95 | memset(opt, 0, 11);
96 | opt->type = htons(41);
97 | opt->udp_payload_size = htons(udp_payload_size);
98 | opt->z = htons(0x8000); // DO-bit
99 | return querysize + 11;
100 | }
101 |
102 | unsigned short getQueryTimestamp()
103 | {
104 | struct timeval tp;
105 | if (gettimeofday(&tp, NULL) == 0) {
106 | return (tp.tv_sec % 6) * 10000 + (tp.tv_usec / 100);
107 | }
108 | return 0;
109 | }
110 |
111 | double getQueryRTT(unsigned short start)
112 | {
113 | unsigned short now = getQueryTimestamp();
114 | unsigned short diff = now - start;
115 | if (now < start)
116 | diff = 60000 - start + now;
117 | return (double)(diff) / 10000.0f;
118 | }
119 |
--------------------------------------------------------------------------------
/debian/copyright:
--------------------------------------------------------------------------------
1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2 | Upstream-Name: dnsmeter
3 | Source: https://codeberg.org/DNS-OARC/dnsmeter
4 |
5 | Files: *
6 | Copyright: 2019-2021 OARC, Inc.
7 | 2019 DENIC eG
8 | License: GPLv3
9 |
10 | Files: debian/*
11 | Copyright: 2021 Jerry Lundström
12 | License: BSD-3-Clause
13 |
14 | Files: src/pplib/*
15 | Copyright: 2019 Patrick Fedick
16 | License: BSD-2-Clause
17 |
18 | License: GPLv3
19 | This is free software: you can redistribute it and/or modify
20 | it under the terms of the GNU General Public License as published by
21 | the Free Software Foundation, either version 3 of the License, or
22 | (at your option) any later version.
23 | .
24 | This is distributed in the hope that it will be useful,
25 | but WITHOUT ANY WARRANTY; without even the implied warranty of
26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 | GNU General Public License for more details.
28 | .
29 | You should have received a copy of the GNU General Public License
30 | along with this. If not, see .
31 |
32 | License: BSD-3-Clause
33 | Redistribution and use in source and binary forms, with or without
34 | modification, are permitted provided that the following conditions
35 | are met:
36 | .
37 | 1. Redistributions of source code must retain the above copyright
38 | notice, this list of conditions and the following disclaimer.
39 | .
40 | 2. Redistributions in binary form must reproduce the above copyright
41 | notice, this list of conditions and the following disclaimer in
42 | the documentation and/or other materials provided with the
43 | distribution.
44 | .
45 | 3. Neither the name of the copyright holder nor the names of its
46 | contributors may be used to endorse or promote products derived
47 | from this software without specific prior written permission.
48 | .
49 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
52 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
53 | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
54 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
55 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
57 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
59 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 | POSSIBILITY OF SUCH DAMAGE.
61 |
62 | Licence: BSD-2-Clause
63 | Redistribution and use in source and binary forms, with or without
64 | modification, are permitted provided that the following conditions are met:
65 | .
66 | 1. Redistributions of source code must retain the above copyright notice,
67 | this list of conditions and the following disclaimer.
68 | 2. Redistributions in binary form must reproduce the above copyright notice,
69 | this list of conditions and the following disclaimer in the documentation
70 | and/or other materials provided with the distribution.
71 | .
72 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
73 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
74 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
75 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
76 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
77 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
78 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
79 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
80 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
81 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
82 |
--------------------------------------------------------------------------------
/m4/ax_compiler_vendor.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_COMPILER_VENDOR
8 | #
9 | # DESCRIPTION
10 | #
11 | # Determine the vendor of the C, C++ or Fortran compiler. The vendor is
12 | # returned in the cache variable $ax_cv_c_compiler_vendor for C,
13 | # $ax_cv_cxx_compiler_vendor for C++ or $ax_cv_fc_compiler_vendor for
14 | # (modern) Fortran. The value is one of "intel", "ibm", "pathscale",
15 | # "clang" (LLVM), "cray", "fujitsu", "sdcc", "sx", "portland" (PGI), "gnu"
16 | # (GCC), "sun" (Oracle Developer Studio), "hp", "dec", "borland",
17 | # "comeau", "kai", "lcc", "sgi", "microsoft", "metrowerks", "watcom",
18 | # "tcc" (Tiny CC) or "unknown" (if the compiler cannot be determined).
19 | #
20 | # To check for a Fortran compiler, you must first call AC_FC_PP_SRCEXT
21 | # with an appropriate preprocessor-enabled extension. For example:
22 | #
23 | # AC_LANG_PUSH([Fortran])
24 | # AC_PROG_FC
25 | # AC_FC_PP_SRCEXT([F])
26 | # AX_COMPILER_VENDOR
27 | # AC_LANG_POP([Fortran])
28 | #
29 | # LICENSE
30 | #
31 | # Copyright (c) 2008 Steven G. Johnson
32 | # Copyright (c) 2008 Matteo Frigo
33 | # Copyright (c) 2018-19 John Zaitseff
34 | #
35 | # This program is free software: you can redistribute it and/or modify it
36 | # under the terms of the GNU General Public License as published by the
37 | # Free Software Foundation, either version 3 of the License, or (at your
38 | # option) any later version.
39 | #
40 | # This program is distributed in the hope that it will be useful, but
41 | # WITHOUT ANY WARRANTY; without even the implied warranty of
42 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
43 | # Public License for more details.
44 | #
45 | # You should have received a copy of the GNU General Public License along
46 | # with this program. If not, see .
47 | #
48 | # As a special exception, the respective Autoconf Macro's copyright owner
49 | # gives unlimited permission to copy, distribute and modify the configure
50 | # scripts that are the output of Autoconf when processing the Macro. You
51 | # need not follow the terms of the GNU General Public License when using
52 | # or distributing such scripts, even though portions of the text of the
53 | # Macro appear in them. The GNU General Public License (GPL) does govern
54 | # all other use of the material that constitutes the Autoconf Macro.
55 | #
56 | # This special exception to the GPL applies to versions of the Autoconf
57 | # Macro released by the Autoconf Archive. When you make and distribute a
58 | # modified version of the Autoconf Macro, you may extend this special
59 | # exception to the GPL to apply to your modified version as well.
60 |
61 | #serial 30
62 |
63 | AC_DEFUN([AX_COMPILER_VENDOR], [dnl
64 | AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, [dnl
65 | dnl If you modify this list of vendors, please add similar support
66 | dnl to ax_compiler_version.m4 if at all possible.
67 | dnl
68 | dnl Note: Do NOT check for GCC first since some other compilers
69 | dnl define __GNUC__ to remain compatible with it. Compilers that
70 | dnl are very slow to start (such as Intel) are listed first.
71 |
72 | vendors="
73 | intel: __ICC,__ECC,__INTEL_COMPILER
74 | ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__,__ibmxl__
75 | pathscale: __PATHCC__,__PATHSCALE__
76 | clang: __clang__
77 | cray: _CRAYC
78 | fujitsu: __FUJITSU
79 | sdcc: SDCC,__SDCC
80 | sx: _SX
81 | portland: __PGI
82 | gnu: __GNUC__
83 | sun: __SUNPRO_C,__SUNPRO_CC,__SUNPRO_F90,__SUNPRO_F95
84 | hp: __HP_cc,__HP_aCC
85 | dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER
86 | borland: __BORLANDC__,__CODEGEARC__,__TURBOC__
87 | comeau: __COMO__
88 | kai: __KCC
89 | lcc: __LCC__
90 | sgi: __sgi,sgi
91 | microsoft: _MSC_VER
92 | metrowerks: __MWERKS__
93 | watcom: __WATCOMC__
94 | tcc: __TINYC__
95 | unknown: UNKNOWN
96 | "
97 | for ventest in $vendors; do
98 | case $ventest in
99 | *:)
100 | vendor=$ventest
101 | continue
102 | ;;
103 | *)
104 | vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")"
105 | ;;
106 | esac
107 |
108 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[
109 | #if !($vencpp)
110 | thisisanerror;
111 | #endif
112 | ]])], [break])
113 | done
114 |
115 | ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
116 | ])
117 | ])dnl
118 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # dnsmeter
2 |
3 | [](https://lgtm.com/projects/g/DNS-OARC/dnsmeter/alerts/) [](https://sonarcloud.io/dashboard?id=dns-oarc%3Adnsmeter) [](https://sonarcloud.io/dashboard?id=dns-oarc%3Adnsmeter)
4 |
5 | `dnsmeter` is a tool for testing performance of a nameserver and the
6 | infrastructure around it. It generates DNS queries and sends them via UDP
7 | to a target nameserver and counts the answers.
8 |
9 | Features:
10 | - payload can be given as a text file or a PCAP file
11 | - can automatically run different load steps, which can be given as a list or ranges
12 | - results per load step can be stored in a CSV file
13 | - sender addresses can be spoofed from a given network or from the addresses found in the PCAP file
14 | - answers are counted, even if source address is spoofed, if answers get routed back to the load generator
15 | - round-trip-times are measured (average, min, mix)
16 | - the amount of DNSSEC queries can be given as percentage of total traffic
17 | - optimized for high amount of packets, on an Intel(R) Xeon(R) CPU E5-2430 v2 @ 2.50GHz it can generate more than 900.000 packets per second
18 | - runs on Linux and FreeBSD
19 |
20 | NOTE:
21 | - Only IPv4 is support
22 |
23 | ## Dependencies
24 |
25 | `dnsmeter` requires a couple of libraries beside a normal C++ compiling
26 | environment with autoconf, automake and libtool.
27 |
28 | `dnsmeter` has a non-optional dependency on the PCRE library, `libresolv`
29 | and PCAP library.
30 |
31 | `dnsmeter` also includes [pplib](https://github.com/DNS-OARC/pplib),
32 | collection of C++ functions and classes, and it has non-optional dependency
33 | on OpenSSL, bzip2, IDN2 (or IDN1) library and zlib.
34 |
35 | To install the dependencies under Debian/Ubuntu:
36 | ```
37 | apt-get install -y libssl-dev libbz2-dev libidn2-dev zlib1g-dev libpcap-dev libpcre3-dev gettext
38 | ```
39 |
40 | NOTE: If your system does not have `libidn2-dev`, please use `libidn11-dev` instead.
41 |
42 | To install the dependencies under CentOS (with EPEL/PowerTools enabled):
43 | ```
44 | yum install -y openssl-devel bzip2-devel libidn2-devel zlib-devel libpcap-devel pcre-devel gettext-devel
45 | ```
46 |
47 | NOTE: If your using openSUSE/SLE then bzip2's package is `libbz2-devel`.
48 |
49 | To install the dependencies under FreeBSD 10+ using `pkg`:
50 | ```
51 | pkg install -y openssl libidn2 libpcap pcre gettext
52 | ```
53 |
54 | ## Building from source tarball
55 |
56 | The [source tarball from DNS-OARC](https://www.dns-oarc.net/tools/dnsmeter)
57 | comes prepared with `configure`:
58 |
59 | ```
60 | tar zxvf dnsmeter-version.tar.gz
61 | cd dnsmeter-version
62 | ./configure [options]
63 | make
64 | make install
65 | ```
66 |
67 | NOTE: If building fails on FreeBSD, try adding these configure
68 | options: `--with-extra-cflags="-I /usr/local/include" --with-extra-ldflags="-L/usr/local/lib"`.
69 |
70 | ## Building from Git repository
71 |
72 | If you are building `dnsmeter` from it's Git repository you will first need
73 | to initiate the Git submodules that exists and later create autoconf/automake
74 | files, this will require a build environment with autoconf, automake and
75 | libtool to be installed.
76 |
77 | ```
78 | git clone https://codeberg.org/DNS-OARC/dnsmeter.git
79 | cd dnsmeter
80 | git submodule update --init
81 | ./autogen.sh
82 | ./configure [options]
83 | make
84 | make install
85 | ```
86 |
87 | ## Usage
88 |
89 | Once installed please see `man dnsmeter` for usage.
90 |
91 | ## Example
92 |
93 | Lets assume the following scenario:
94 |
95 | - load generator runs on FreeBSD
96 | - network interface an which the traffic goes out and comes back is `igb0`
97 | - source IP on the load generator is 192.168.155.20
98 | - target nameserver has IP 192.168.0.1, port 53
99 | - we want to spoof the sender address from the network 10.0.0.0/8
100 | - the payload file is found here: `/home/testdata/payload.txt`
101 | - the nameserver is running on CentOS and we need to set a route back to the load generator: `ip route add 10.0.0.0/8 via 192.168.155.20`
102 | - we want to test the following load steps: 30000,40000,45000,50000,100000,150000
103 | - results should be written to `results.csv`
104 | - DNSSEC rate should be 70%
105 |
106 | This makes the following command:
107 |
108 | ```
109 | dnsmeter -p /home/testdata/payload.txt \
110 | -r 30000,40000,45000,50000,100000,150000 \
111 | -s 10.0.0.0/8 \
112 | -z 192.168.0.1:53 \
113 | -e igb0 \
114 | -d 70 \
115 | -c results.csv
116 | ```
117 |
118 | In the second example, we want to use a PCAP file as payload and want
119 | to spoof with the addresses from that file:
120 |
121 | ```
122 | dnsmeter -p /home/testdata/pcap.file1 \
123 | -r 30000,40000,45000,50000,100000,150000 \
124 | -s pcap \
125 | -z 192.168.0.1:53 \
126 | -e igb0 \
127 | -c results_pcap.csv
128 | ```
129 |
130 | ## Author(s)
131 |
132 | - Patrick Fedick [@pfedick](https://github.com/pfedick)
133 |
134 | ## Contributor(s)
135 |
136 | - Jerry Lundström [@jelu](https://github.com/jelu)
137 |
138 | ## Copyright
139 |
140 | Copyright (c) 2019-2021, OARC, Inc.
141 |
142 | Copyright (c) 2019, DENIC eG
143 |
144 | All rights reserved.
145 |
146 | ```
147 | This file is part of dnsmeter.
148 |
149 | dnsmeter is free software: you can redistribute it and/or modify
150 | it under the terms of the GNU General Public License as published by
151 | the Free Software Foundation, either version 3 of the License, or
152 | (at your option) any later version.
153 |
154 | dnsmeter is distributed in the hope that it will be useful,
155 | but WITHOUT ANY WARRANTY; without even the implied warranty of
156 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
157 | GNU General Public License for more details.
158 |
159 | You should have received a copy of the GNU General Public License
160 | along with dnsmeter. If not, see .
161 | ```
162 |
--------------------------------------------------------------------------------
/src/payload_file.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "config.h"
23 |
24 | #include "payload_file.h"
25 | #include "exceptions.h"
26 | #include "query.h"
27 |
28 | #define __FAVOR_BSD 1
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | #pragma pack(push) /* push current alignment to stack */
36 | #pragma pack(1) /* set alignment to 1 byte boundary */
37 | struct ETHER {
38 | unsigned char destination[6];
39 | unsigned char source[6];
40 | unsigned short type;
41 | };
42 | #pragma pack(pop) /* restore original alignment from stack */
43 |
44 | PayloadFile::PayloadFile()
45 | {
46 | validLinesInQueryFile = 0;
47 | payloadIsPcap = false;
48 | }
49 |
50 | bool PayloadFile::detectPcap(ppl7::File& ff)
51 | {
52 | unsigned char buffer[8];
53 | if (ff.read(buffer, 8) != 8) {
54 | ff.seek(0);
55 | return false;
56 | }
57 | ff.seek(0);
58 | unsigned int magic = ppl7::Peek32(buffer + 0);
59 | if (magic == 0xa1b2c3d4 || magic == 0xa1b23c4d)
60 | return true;
61 | if (magic == 0xd4c3b2a1 || magic == 0x4d3cb2a1)
62 | return true;
63 | return false;
64 | }
65 |
66 | void PayloadFile::openQueryFile(const ppl7::String& Filename)
67 | {
68 | if (Filename.isEmpty())
69 | throw InvalidQueryFile("File not given");
70 | ppl7::File QueryFile;
71 | QueryFile.open(Filename, ppl7::File::READ);
72 | if (QueryFile.size() == 0) {
73 | throw InvalidQueryFile("File is empty [%s]", (const char*)Filename);
74 | }
75 | printf("INFO: Loading and precompile payload. This could take some time...\n");
76 | if (detectPcap(QueryFile)) {
77 | loadAndCompilePcapFile(Filename);
78 | } else {
79 | loadAndCompile(QueryFile);
80 | }
81 | printf("INFO: %llu queries loaded\n", validLinesInQueryFile);
82 | it = querycache.begin();
83 | }
84 |
85 | void PayloadFile::loadAndCompile(ppl7::File& ff)
86 | {
87 | ppl7::ByteArray buf(4096);
88 | ppl7::String buffer;
89 | validLinesInQueryFile = 0;
90 | unsigned char* compiled_query = (unsigned char*)buf.ptr();
91 | while (1) {
92 | try {
93 | if (ff.eof())
94 | throw ppl7::EndOfFileException();
95 | ff.gets(buffer, 1024);
96 | buffer.trim();
97 | if (buffer.isEmpty())
98 | continue;
99 | if (buffer.c_str()[0] == '#')
100 | continue;
101 | try {
102 | // Precompile Query
103 | int size = MakeQuery(buffer, compiled_query, 4096, false);
104 | querycache.push_back(ppl7::ByteArray(compiled_query, size));
105 | validLinesInQueryFile++;
106 | } catch (...) {
107 | // ignore invalid queries
108 | continue;
109 | }
110 | } catch (const ppl7::EndOfFileException&) {
111 | if (validLinesInQueryFile == 0) {
112 | throw InvalidQueryFile("No valid Queries found in Queryfile");
113 | }
114 | return;
115 | }
116 | }
117 | }
118 |
119 | void PayloadFile::loadAndCompilePcapFile(const ppl7::String& Filename)
120 | {
121 | char errorbuffer[PCAP_ERRBUF_SIZE];
122 | struct pcap_pkthdr hdr;
123 | payloadIsPcap = true;
124 | validLinesInQueryFile = 0;
125 | pcap_t* pp = pcap_open_offline((const char*)Filename, errorbuffer);
126 | if (!pp)
127 | throw InvalidQueryFile("%s", errorbuffer);
128 | ppluint64 pkts_total = 0;
129 | const u_char* pkt;
130 | while ((pkt = pcap_next(pp, &hdr)) != NULL) {
131 | pkts_total++;
132 | //printf ("len=%d, caplen=%d\n",hdr.len,hdr.caplen);
133 | const struct ETHER* eth = (const struct ETHER*)pkt;
134 | if (hdr.caplen > 4096)
135 | continue;
136 | if (eth->type != htons(0x0800))
137 | continue;
138 | const struct ip* iphdr = (const struct ip*)(pkt + 14);
139 | if (iphdr->ip_v != 4)
140 | continue;
141 | const struct udphdr* udp = (const struct udphdr*)(pkt + 14 + sizeof(struct ip));
142 | if (udp->uh_dport != htons(53))
143 | continue;
144 | const struct DNS_HEADER* dns = (const struct DNS_HEADER*)(pkt + 14 + sizeof(struct ip) + sizeof(struct udphdr));
145 | if (dns->qr != 0 || dns->opcode != 0)
146 | continue;
147 | querycache.push_back(ppl7::ByteArray(pkt, hdr.caplen));
148 | validLinesInQueryFile++;
149 | }
150 | printf("Packets read from pcap file: %llu, valid UDP DNS queries: %llu\n",
151 | pkts_total, validLinesInQueryFile);
152 | pcap_close(pp);
153 | if (validLinesInQueryFile == 0) {
154 | throw InvalidQueryFile("No valid Queries found in pcap file [%s]", (const char*)Filename);
155 | }
156 | }
157 |
158 | const ppl7::ByteArrayPtr& PayloadFile::getQuery()
159 | {
160 | QueryMutex.lock();
161 | const ppl7::ByteArrayPtr& bap = *it;
162 | ++it;
163 | if (it == querycache.end())
164 | it = querycache.begin();
165 | QueryMutex.unlock();
166 | return bap;
167 | }
168 |
169 | bool PayloadFile::isPcap()
170 | {
171 | return payloadIsPcap;
172 | }
173 |
--------------------------------------------------------------------------------
/m4/ax_cflags_warn_all.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # https://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_CFLAGS_WARN_ALL [(shellvar[, default[, action-if-found[, action-if-not-found]]])]
8 | # AX_CXXFLAGS_WARN_ALL [(shellvar[, default[, action-if-found[, action-if-not-found]]])]
9 | # AX_FCFLAGS_WARN_ALL [(shellvar[, default[, action-if-found[, action-if-not-found]]])]
10 | #
11 | # DESCRIPTION
12 | #
13 | # Specify compiler options that enable most reasonable warnings. For the
14 | # GNU Compiler Collection (GCC), for example, it will be "-Wall". The
15 | # result is added to shellvar, one of CFLAGS, CXXFLAGS or FCFLAGS if the
16 | # first parameter is not specified.
17 | #
18 | # Each of these macros accepts the following optional arguments:
19 | #
20 | # - $1 - shellvar
21 | # shell variable to use (CFLAGS, CXXFLAGS or FCFLAGS if not
22 | # specified, depending on macro)
23 | #
24 | # - $2 - default
25 | # value to use for flags if compiler vendor cannot be determined (by
26 | # default, "")
27 | #
28 | # - $3 - action-if-found
29 | # action to take if the compiler vendor has been successfully
30 | # determined (by default, add the appropriate compiler flags to
31 | # shellvar)
32 | #
33 | # - $4 - action-if-not-found
34 | # action to take if the compiler vendor has not been determined or
35 | # is unknown (by default, add the default flags, or "" if not
36 | # specified, to shellvar)
37 | #
38 | # These macros use AX_COMPILER_VENDOR to determine which flags should be
39 | # returned for a given compiler. Not all compilers currently have flags
40 | # defined for them; patches are welcome. If need be, compiler flags may
41 | # be made language-dependent: use a construct like the following:
42 | #
43 | # [vendor_name], [m4_if(_AC_LANG_PREFIX,[C], VAR="--relevant-c-flags",dnl
44 | # m4_if(_AC_LANG_PREFIX,[CXX], VAR="--relevant-c++-flags",dnl
45 | # m4_if(_AC_LANG_PREFIX,[FC], VAR="--relevant-fortran-flags",dnl
46 | # VAR="$2"; FOUND="no")))],
47 | #
48 | # Note: These macros also depend on AX_PREPEND_FLAG.
49 | #
50 | # LICENSE
51 | #
52 | # Copyright (c) 2008 Guido U. Draheim
53 | # Copyright (c) 2010 Rhys Ulerich
54 | # Copyright (c) 2018 John Zaitseff
55 | #
56 | # This program is free software; you can redistribute it and/or modify it
57 | # under the terms of the GNU General Public License as published by the
58 | # Free Software Foundation; either version 3 of the License, or (at your
59 | # option) any later version.
60 | #
61 | # This program is distributed in the hope that it will be useful, but
62 | # WITHOUT ANY WARRANTY; without even the implied warranty of
63 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
64 | # Public License for more details.
65 | #
66 | # You should have received a copy of the GNU General Public License along
67 | # with this program. If not, see .
68 | #
69 | # As a special exception, the respective Autoconf Macro's copyright owner
70 | # gives unlimited permission to copy, distribute and modify the configure
71 | # scripts that are the output of Autoconf when processing the Macro. You
72 | # need not follow the terms of the GNU General Public License when using
73 | # or distributing such scripts, even though portions of the text of the
74 | # Macro appear in them. The GNU General Public License (GPL) does govern
75 | # all other use of the material that constitutes the Autoconf Macro.
76 | #
77 | # This special exception to the GPL applies to versions of the Autoconf
78 | # Macro released by the Autoconf Archive. When you make and distribute a
79 | # modified version of the Autoconf Macro, you may extend this special
80 | # exception to the GPL to apply to your modified version as well.
81 |
82 | #serial 25
83 |
84 | AC_DEFUN([AX_FLAGS_WARN_ALL], [
85 | AX_REQUIRE_DEFINED([AX_PREPEND_FLAG])dnl
86 | AC_REQUIRE([AX_COMPILER_VENDOR])dnl
87 |
88 | AS_VAR_PUSHDEF([FLAGS], [m4_default($1,_AC_LANG_PREFIX[]FLAGS)])dnl
89 | AS_VAR_PUSHDEF([VAR], [ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl
90 | AS_VAR_PUSHDEF([FOUND], [ac_save_[]_AC_LANG_ABBREV[]flags_warn_all_found])dnl
91 |
92 | AC_CACHE_CHECK([FLAGS for most reasonable warnings], VAR, [
93 | VAR=""
94 | FOUND="yes"
95 | dnl Cases are listed in the order found in ax_compiler_vendor.m4
96 | AS_CASE("$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor",
97 | [intel], [VAR="-w2"],
98 | [ibm], [VAR="-qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd"],
99 | [pathscale], [],
100 | [clang], [VAR="-Wall"],
101 | [cray], [VAR="-h msglevel 2"],
102 | [fujitsu], [],
103 | [sdcc], [],
104 | [sx], [VAR="-pvctl[,]fullmsg"],
105 | [portland], [],
106 | [gnu], [VAR="-Wall"],
107 | [sun], [VAR="-v"],
108 | [hp], [VAR="+w1"],
109 | [dec], [VAR="-verbose -w0 -warnprotos"],
110 | [borland], [],
111 | [comeau], [],
112 | [kai], [],
113 | [lcc], [],
114 | [sgi], [VAR="-fullwarn"],
115 | [microsoft], [],
116 | [metrowerks], [],
117 | [watcom], [],
118 | [tcc], [],
119 | [unknown], [
120 | VAR="$2"
121 | FOUND="no"
122 | ],
123 | [
124 | AC_MSG_WARN([Unknown compiler vendor returned by [AX_COMPILER_VENDOR]])
125 | VAR="$2"
126 | FOUND="no"
127 | ]
128 | )
129 |
130 | AS_IF([test "x$FOUND" = "xyes"], [dnl
131 | m4_default($3, [AS_IF([test "x$VAR" != "x"], [AX_PREPEND_FLAG([$VAR], [FLAGS])])])
132 | ], [dnl
133 | m4_default($4, [m4_ifval($2, [AX_PREPEND_FLAG([$VAR], [FLAGS])], [true])])
134 | ])dnl
135 | ])dnl
136 |
137 | AS_VAR_POPDEF([FOUND])dnl
138 | AS_VAR_POPDEF([VAR])dnl
139 | AS_VAR_POPDEF([FLAGS])dnl
140 | ])dnl AX_FLAGS_WARN_ALL
141 |
142 | AC_DEFUN([AX_CFLAGS_WARN_ALL], [dnl
143 | AC_LANG_PUSH([C])
144 | AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
145 | AC_LANG_POP([C])
146 | ])dnl
147 |
148 | AC_DEFUN([AX_CXXFLAGS_WARN_ALL], [dnl
149 | AC_LANG_PUSH([C++])
150 | AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
151 | AC_LANG_POP([C++])
152 | ])dnl
153 |
154 | AC_DEFUN([AX_FCFLAGS_WARN_ALL], [dnl
155 | AC_LANG_PUSH([Fortran])
156 | AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
157 | AC_LANG_POP([Fortran])
158 | ])dnl
159 |
--------------------------------------------------------------------------------
/src/packet.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "config.h"
23 |
24 | #include "packet.h"
25 | #include "exceptions.h"
26 | #include "query.h"
27 |
28 | #define __FAVOR_BSD 1
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | #define USZ sizeof(struct udphdr)
36 | #define ISZ sizeof(struct ip)
37 | #define HDRSZ ISZ + USZ
38 | #define MAXPACKETSIZE 4096
39 |
40 | static unsigned short in_cksum(unsigned short* addr, int len)
41 | {
42 | int nleft = len;
43 | unsigned short* w = addr;
44 | int sum = 0;
45 | unsigned short answer = 0;
46 | while (nleft > 1) {
47 | sum += *w++;
48 | nleft -= 2;
49 | }
50 | if (nleft == 1) {
51 | *(unsigned char*)(&answer) = *(unsigned char*)w;
52 | sum += answer;
53 | }
54 | sum = (sum >> 16) + (sum & 0xffff);
55 | sum += (sum >> 16);
56 | answer = ~sum;
57 | return (answer);
58 | }
59 |
60 | static unsigned short udp_cksum(const struct ip* iphdr, const struct udphdr* udp, const unsigned char* payload, size_t payload_size)
61 | {
62 | unsigned char cbuf[MAXPACKETSIZE];
63 | memset(cbuf, 0, sizeof(cbuf));
64 | unsigned char* p = (unsigned char*)cbuf;
65 | *(unsigned int*)p = iphdr->ip_src.s_addr;
66 | p += sizeof(unsigned int);
67 | *(unsigned int*)p = iphdr->ip_dst.s_addr;
68 | p += sizeof(unsigned int);
69 | *(unsigned char*)p++ = 0;
70 | *(unsigned char*)p++ = iphdr->ip_p;
71 | *(unsigned short*)p = udp->uh_ulen;
72 | p += sizeof(unsigned short);
73 | memcpy(p, udp, USZ);
74 | p += USZ;
75 | memcpy(p, payload, payload_size);
76 | return in_cksum((unsigned short*)cbuf, sizeof(uint) * 3 + sizeof(struct udphdr) + payload_size + (payload_size % 2));
77 | }
78 |
79 | Packet::Packet()
80 | {
81 | buffersize = MAXPACKETSIZE;
82 | payload_size = 0;
83 | buffer = (unsigned char*)calloc(1, buffersize);
84 | if (!buffer)
85 | throw ppl7::OutOfMemoryException();
86 |
87 | struct ip* iphdr = (struct ip*)buffer;
88 | struct udphdr* udp = (struct udphdr*)(buffer + ISZ);
89 |
90 | iphdr->ip_hl = ISZ >> 2;
91 | iphdr->ip_v = IPVERSION;
92 | iphdr->ip_tos = 0;
93 | iphdr->ip_off = 0;
94 | iphdr->ip_ttl = 64;
95 | iphdr->ip_p = IPPROTO_UDP;
96 | iphdr->ip_sum = 0;
97 | iphdr->ip_id = 0;
98 | iphdr->ip_src.s_addr = 0;
99 | iphdr->ip_dst.s_addr = 0;
100 | iphdr->ip_len = htons(HDRSZ + payload_size);
101 | iphdr->ip_sum = in_cksum((unsigned short*)iphdr, ISZ);
102 |
103 | udp->uh_ulen = htons(USZ + payload_size);
104 | chksum_valid = false;
105 | }
106 |
107 | Packet::~Packet()
108 | {
109 | free(buffer);
110 | }
111 |
112 | void Packet::setSource(const ppl7::IPAddress& ip_addr, int port)
113 | {
114 | struct ip* iphdr = (struct ip*)buffer;
115 | struct udphdr* udp = (struct udphdr*)(buffer + ISZ);
116 | iphdr->ip_src.s_addr = *(in_addr_t*)ip_addr.addr();
117 | udp->uh_sport = htons(port);
118 | chksum_valid = false;
119 | }
120 |
121 | void Packet::randomSourcePort()
122 | {
123 | struct udphdr* udp = (struct udphdr*)(buffer + ISZ);
124 | udp->uh_sport = htons(ppl7::rand(1024, 65535));
125 | chksum_valid = false;
126 | }
127 |
128 | void Packet::randomSourceIP(const ppl7::IPNetwork& net)
129 | {
130 | struct ip* iphdr = (struct ip*)buffer;
131 | in_addr_t start = ntohl(*(in_addr_t*)net.first().addr());
132 | size_t size = powl(2, 32 - net.prefixlen());
133 | iphdr->ip_src.s_addr = htonl(ppl7::rand(start, start + size - 1));
134 | chksum_valid = false;
135 | }
136 |
137 | void Packet::randomSourceIP(unsigned int start, unsigned int size)
138 | {
139 | struct ip* iphdr = (struct ip*)buffer;
140 | iphdr->ip_src.s_addr = htonl(ppl7::rand(start, start + size - 1));
141 | chksum_valid = false;
142 | }
143 |
144 | void Packet::useSourceFromPcap(const char* pkt, size_t size)
145 | {
146 | const struct ip* s_iphdr = (const struct ip*)(pkt + 14);
147 | const struct udphdr* s_udp = (const struct udphdr*)(pkt + 14 + sizeof(struct ip));
148 | struct ip* iphdr = (struct ip*)buffer;
149 | struct udphdr* udp = (struct udphdr*)(buffer + ISZ);
150 | iphdr->ip_src.s_addr = s_iphdr->ip_src.s_addr;
151 | udp->uh_sport = s_udp->uh_sport;
152 | }
153 |
154 | void Packet::setDestination(const ppl7::IPAddress& ip_addr, int port)
155 | {
156 | struct ip* iphdr = (struct ip*)buffer;
157 | struct udphdr* udp = (struct udphdr*)(buffer + ISZ);
158 | iphdr->ip_dst.s_addr = *(in_addr_t*)ip_addr.addr();
159 | udp->uh_dport = htons(port);
160 | chksum_valid = false;
161 | }
162 |
163 | void Packet::setIpId(unsigned short id)
164 | {
165 | struct ip* iphdr = (struct ip*)buffer;
166 | iphdr->ip_id = htons(id);
167 | chksum_valid = false;
168 | }
169 |
170 | void Packet::setDnsId(unsigned short id)
171 | {
172 | *((unsigned short*)(buffer + HDRSZ)) = htons(id);
173 | chksum_valid = false;
174 | }
175 |
176 | void Packet::setPayload(const void* payload, size_t size)
177 | {
178 | if (size + HDRSZ > MAXPACKETSIZE)
179 | throw BufferOverflow("%zd > %zd", size, MAXPACKETSIZE - HDRSZ);
180 | memcpy(buffer + HDRSZ, payload, size);
181 | payload_size = size;
182 | struct ip* iphdr = (struct ip*)buffer;
183 | struct udphdr* udp = (struct udphdr*)(buffer + ISZ);
184 | iphdr->ip_len = htons(HDRSZ + payload_size);
185 | udp->uh_ulen = htons(USZ + payload_size);
186 | chksum_valid = false;
187 | }
188 |
189 | void Packet::setPayloadDNSQuery(const ppl7::String& query, bool dnssec)
190 | {
191 | payload_size = MakeQuery(query, buffer + HDRSZ, buffersize - HDRSZ, dnssec);
192 | struct ip* iphdr = (struct ip*)buffer;
193 | struct udphdr* udp = (struct udphdr*)(buffer + ISZ);
194 | iphdr->ip_len = htons(HDRSZ + payload_size);
195 | udp->uh_ulen = htons(USZ + payload_size);
196 | chksum_valid = false;
197 | }
198 |
199 | void Packet::updateChecksums()
200 | {
201 | struct ip* iphdr = (struct ip*)buffer;
202 | struct udphdr* udp = (struct udphdr*)(buffer + ISZ);
203 | iphdr->ip_sum = 0;
204 | iphdr->ip_sum = in_cksum((unsigned short*)iphdr, ISZ);
205 | udp->uh_sum = 0;
206 | udp->uh_sum = udp_cksum(iphdr, udp, buffer + HDRSZ, payload_size);
207 | chksum_valid = true;
208 | }
209 |
210 | size_t Packet::size() const
211 | {
212 | return HDRSZ + payload_size;
213 | }
214 |
215 | unsigned char* Packet::ptr()
216 | {
217 | if (!chksum_valid)
218 | updateChecksums();
219 | return buffer;
220 | }
221 |
--------------------------------------------------------------------------------
/src/dnsmeter.1.in:
--------------------------------------------------------------------------------
1 | .\" Copyright (c) 2019-2021, OARC, Inc.
2 | .\" Copyright (c) 2019, DENIC eG
3 | .\" All rights reserved.
4 | .\"
5 | .\" This file is part of dnsmeter.
6 | .\"
7 | .\" dnsmeter is free software: you can redistribute it and/or modify
8 | .\" it under the terms of the GNU General Public License as published by
9 | .\" the Free Software Foundation, either version 3 of the License, or
10 | .\" (at your option) any later version.
11 | .\"
12 | .\" dnsmeter is distributed in the hope that it will be useful,
13 | .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | .\" GNU General Public License for more details.
16 | .\"
17 | .\" You should have received a copy of the GNU General Public License
18 | .\" along with dnsmeter. If not, see .
19 | .TH dnsmeter 1 "@PACKAGE_VERSION@" "dnsmeter"
20 | .SH NAME
21 | dnsmeter \- DNS performance and infrastructure testing
22 | .SH SYNOPSIS
23 | .hy 0
24 | .ad l
25 | \fBdnsmeter\fR\ [\fB\-h\fR]
26 | [\fB\-q\ \fIHOST\fR]
27 | [\fB\-s\ \fINET|pcap\fR]
28 | [\fB\-e\ \fIETH\fR]
29 | [\fB\-z\ \fIHOST:PORT\fR]
30 | [\fB\-p\ \fIFILE\fR]
31 | [\fB\-l\ \fI#\fR]
32 | [\fB\-t\ \fI#\fR]
33 | [\fB\-n\ \fI#\fR]
34 | [\fB\-r\ \fI#\fR]
35 | [\fB\-d\ \fI#\fR]
36 | [\fB\-c\ \fIFILE\fR]
37 | [\fB\--ignore\fR]
38 | .ad
39 | .hy
40 | .SH DESCRIPTION
41 | DNSMeter is a tool for testing performance of nameserver and/or
42 | infrastructure around it.
43 | It generates dns queries and sends them via UDP to a target nameserver
44 | and counts the answers.
45 |
46 | Features:
47 | .br
48 | - payload can be given as text file or PCAP file
49 | .br
50 | - can automatically run different load steps, which can be given as
51 | list or ranges
52 | .br
53 | - results per load step can be stored in CSV file
54 | .br
55 | - sender address can be spoofed from a given network or from PCAP file,
56 | if payload is a PCAP file
57 | .br
58 | - answers are counted, even if source address is spoofed, if answers get
59 | routed back to the load generator
60 | .br
61 | - roundtrip-times are measured (average, min, mix)
62 | .br
63 | - amount of DNSSEC queries can be given as percentage of total traffic
64 | .br
65 | - optimized for high amount of packets. On an Intel(R) Xeon(R) CPU E5-2430
66 | v2 @ 2.50GHz it can generate more than 900.000 packets per second
67 | .SH OPTIONS
68 | .TP
69 | .B -h
70 | Show option help.
71 | .TP
72 | .BI -q \ HOST
73 | Hostname or IP address of sender if you don't want to spoof (see
74 | .IR -s ).
75 | .TP
76 | .BI -s \ NET|pcap
77 | Spoof sender address.
78 | Use random IP from the given network (example:
79 | .IR 192.168.0.0/16 ).
80 | Only works when running as root!
81 | If payload is a PCAP file, you can use
82 | .BI -s pcap
83 | to use the source addresses and ports from the PCAP file.
84 | .TP
85 | .BI -e \ ETH
86 | Interface on which the packet receiver should listen (FreeBSD only).
87 | .TP
88 | .BI -z \ HOST:PORT
89 | Hostname or IP address and port of the target nameserver.
90 | .TP
91 | .BI -p \ FILE
92 | File with queries/payload or PCAP file.
93 | .TP
94 | .BI -l \ #
95 | Runtime in seconds (default=10 seconds).
96 | .TP
97 | .BI -t \ #
98 | Timeout in seconds (default=2 seconds).
99 | .TP
100 | .BI -n \ #
101 | Number of worker threads (default=1).
102 | .TP
103 | .BI -r \ #
104 | Query rate (Default=as much as possible) can be a single value, a comma
105 | separated list (rate,rate,...) or a range and a step value (start - end,
106 | step).
107 | .TP
108 | .BI -d \ #
109 | Amount of queries in percent on which the DNSSEC-flags are set (default=0).
110 | .TP
111 | .BI -c \ FILE
112 | CSV-file for results.
113 | .TP
114 | .B --ignore
115 | Answers are ignored and therefor not counted.
116 | In this mode the tool only generates traffic.
117 | .SH USAGE
118 | This section contains additional usage information not covered by
119 | the options documentation.
120 |
121 | .BI -q \ HOST
122 | |
123 | .BI -s \ NETWORK
124 | |
125 | .BI -s \ pcap
126 |
127 | Source IP, hostname or network from which the packets should be send.
128 | If you dont't want to spoof, use
129 | .I -q
130 | with a single IP address or hostname.
131 | Use
132 | .I -s
133 | followed by a network, if you want to spoof the source address.
134 | .B dnsmeter
135 | will generated random IP addresses inside this network.
136 | Example:
137 | .B -s
138 | .IR 10.0.0.0/8 .
139 |
140 | If payload is a PCAP file, you can use the source addresses and ports
141 | from the PCAP file, if you use
142 | .B -s
143 | .IR pcap .
144 |
145 | .BI -e \ ETH
146 |
147 | Ignored on Linux, but on FreeBSD you have to enter the name of the
148 | network interface on which the tool should listen for the answers.
149 |
150 | .BI -p \ FILE
151 |
152 | File with payload in text format or PCAP file.
153 | When using a text format each line must contain one query with name
154 | and record type.
155 |
156 | Example:
157 |
158 | www.denic.de A
159 | denic.de NS
160 | ...
161 |
162 | .IR NOTE :
163 | the file should not be too big, because it is completely
164 | loaded into memory and pre-compiled to DNS query packets.
165 |
166 | .BI -n \ #
167 |
168 | Number of worker threads, recommendation:
169 | .br
170 | - less than 200000 packets per second: 1 Thread
171 | .br
172 | - 200000 - 500000 packets per second: 2 Threads
173 | .br
174 | - more than 500000 packets per second: 4 Threads
175 |
176 | .BI NOTE :
177 | this is CPU dependent!
178 | If you have a fast CPU, you may need lesser threads, on a slow CPU you
179 | may need more threads.
180 | Don't use more threads than cores available on your CPU, minus one!
181 |
182 | .BI -r \ #[,#,#]
183 |
184 | Query rate or load steps.
185 | Can be a single value if you want to test a specific query rate, a comma
186 | separated list or a range with step with.
187 |
188 | Examples:
189 | .br
190 | - Single value: -r 100000
191 | .br
192 | - a list of query rates: -r 10000,20000,30000,40000,50000,60000
193 | .br
194 | - a range with step: -r 10000-200000,10000
195 |
196 | .BI -d \ #
197 |
198 | Amount of DNSSEC queries in percentage between 0 and 100.
199 | Is ignored, if using PCAP file as payload.
200 |
201 | .BI -c \ FILENAME
202 |
203 | Filename for results in CSV format.
204 |
205 | .BI NOTE :
206 | if file exists, results are appended!
207 |
208 | .SH EXAMPLE
209 |
210 | Lets assume the following scenario:
211 | .br
212 | - load generator runs on FreeBSD
213 | .br
214 | - network interface an which the traffic goes out and comes back is "igb0"
215 | .br
216 | - source ip on the load generator is 192.168.155.20
217 | .br
218 | - target nameserver has ip 192.168.0.1, port 53
219 | .br
220 | - we want to spoof the sender address from the network 10.0.0.0/8
221 | .br
222 | - the payload file is found here: /home/testdata/payload.txt
223 | .br
224 | - the nameserver is running on CentOS and we need to set a route back to the load generator:
225 | .br
226 | ip route add 10.0.0.0/8 via 192.168.155.20
227 | .br
228 | - we want to test the following load steps: 30000,40000,45000,50000,100000,150000
229 | .br
230 | - results should be written to results.csv
231 | .br
232 | - DNSSEC rate should be 70%
233 |
234 | This makes the following command:
235 |
236 | dnsmeter -p /home/testdata/payload.txt \\
237 | -r 30000,40000,45000,50000,100000,150000 \\
238 | -s 10.0.0.0/8 \\
239 | -z 192.168.0.1:53 \\
240 | -e igb0 \\
241 | -d 70 \\
242 | -c results.csv
243 |
244 | In the second example, we want to use a PCAP file as payload and want
245 | to spoof with the addresses from that file:
246 |
247 | dnsmeter -p /home/testdata/pcap.file1 \\
248 | -r 30000,40000,45000,50000,100000,150000 \\
249 | -s pcap \\
250 | -z 192.168.0.1:53 \\
251 | -e igb0 \\
252 | -c results_pcap.csv
253 |
254 | .SH AUTHOR
255 | Patrick Fedick
256 | .RI ( https://github.com/pfedick )
257 | .LP
258 | Maintained by DNS-OARC
259 | .LP
260 | .RS
261 | .I https://www.dns-oarc.net/
262 | .RE
263 | .LP
264 | .SH BUGS
265 | For issues and feature requests please use:
266 | .LP
267 | .RS
268 | \fI@PACKAGE_URL@\fP
269 | .RE
270 | .LP
271 | For question and help please use:
272 | .LP
273 | .RS
274 | \fI@PACKAGE_BUGREPORT@\fP
275 | .RE
276 | .LP
277 |
--------------------------------------------------------------------------------
/src/dns_sender_thread.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "config.h"
23 |
24 | #include "dns_sender_thread.h"
25 | #include "query.h"
26 | #include "exceptions.h"
27 |
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | DNSSenderThread::DNSSenderThread()
37 | {
38 | buffer = (unsigned char*)malloc(4096);
39 | if (!buffer)
40 | throw ppl7::OutOfMemoryException();
41 | Timeslice = 0.0f;
42 | runtime = 10;
43 | timeout = 5;
44 | queryrate = 0;
45 | counter_packets_send = 0;
46 | counter_bytes_send = 0;
47 | errors = 0;
48 | counter_0bytes = 0;
49 | duration = 0.0;
50 | for (int i = 0; i < 255; i++)
51 | counter_errorcodes[i] = 0;
52 | verbose = false;
53 | spoofingEnabled = false;
54 | DnssecRate = 0;
55 | dnsseccounter = 0;
56 | payload = NULL;
57 | spoofing_net_start = 0;
58 | spoofing_net_size = 0;
59 | payloadIsPcap = false;
60 | spoofingFromPcap = false;
61 | }
62 |
63 | DNSSenderThread::~DNSSenderThread()
64 | {
65 | free(buffer);
66 | }
67 |
68 | void DNSSenderThread::setDestination(const ppl7::IPAddress& ip, int port)
69 | {
70 | Socket.setDestination(ip, port);
71 | pkt.setDestination(ip, port);
72 | }
73 |
74 | void DNSSenderThread::setPayload(PayloadFile& payload)
75 | {
76 | this->payload = &payload;
77 | this->payloadIsPcap = payload.isPcap();
78 | }
79 |
80 | void DNSSenderThread::setRuntime(int seconds)
81 | {
82 | runtime = seconds;
83 | }
84 |
85 | void DNSSenderThread::setTimeout(int seconds)
86 | {
87 | timeout = seconds;
88 | }
89 |
90 | void DNSSenderThread::setDNSSECRate(int rate)
91 | {
92 | DnssecRate = rate;
93 | }
94 |
95 | void DNSSenderThread::setQueryRate(ppluint64 qps)
96 | {
97 | queryrate = qps;
98 | }
99 |
100 | void DNSSenderThread::setTimeslice(float ms)
101 | {
102 | if (ms == 0.0f || ms > 1000.0f)
103 | throw ppl7::InvalidArgumentsException();
104 | //if ((1000 % ms)!=0) throw ppl7::InvalidArgumentsException();
105 | Timeslice = (double)ms / 1000;
106 | }
107 |
108 | void DNSSenderThread::setSourceIP(const ppl7::IPAddress& ip)
109 | {
110 | sourceip = ip;
111 | spoofingEnabled = false;
112 | }
113 |
114 | void DNSSenderThread::setSourceNet(const ppl7::IPNetwork& net)
115 | {
116 | sourcenet = net;
117 | spoofingEnabled = true;
118 | spoofing_net_start = ntohl(*(in_addr_t*)net.first().addr());
119 | spoofing_net_size = powl(2, 32 - net.prefixlen());
120 | }
121 |
122 | void DNSSenderThread::setSourcePcap()
123 | {
124 | spoofingEnabled = true;
125 | spoofingFromPcap = true;
126 | }
127 |
128 | void DNSSenderThread::setVerbose(bool verbose)
129 | {
130 | this->verbose = verbose;
131 | }
132 |
133 | #define PCAP_HEADER_SIZE 14 + sizeof(struct ip) + sizeof(struct udphdr)
134 |
135 | void DNSSenderThread::sendPacket()
136 | {
137 | size_t query_size;
138 | while (1) {
139 | try {
140 | const ppl7::ByteArrayPtr& bap = payload->getQuery();
141 | query_size = bap.size();
142 | if (payloadIsPcap) {
143 | query_size -= PCAP_HEADER_SIZE;
144 | memcpy(buffer, ((const char*)bap.ptr()) + PCAP_HEADER_SIZE, query_size);
145 | } else {
146 | memcpy(buffer, bap.ptr(), query_size);
147 | dnsseccounter += DnssecRate;
148 | if (dnsseccounter >= 100) {
149 | query_size = AddDnssecToQuery(buffer, 4096, query_size);
150 | dnsseccounter -= 100;
151 | }
152 | }
153 | pkt.setPayload(buffer, query_size);
154 | if (spoofingEnabled) {
155 | if (spoofingFromPcap) {
156 | pkt.useSourceFromPcap((const char*)bap.ptr(), bap.size());
157 | } else {
158 | pkt.randomSourceIP(spoofing_net_start, spoofing_net_size);
159 | pkt.randomSourcePort();
160 | }
161 | } else {
162 | pkt.randomSourcePort();
163 | }
164 | pkt.setDnsId(getQueryTimestamp());
165 | ssize_t n = Socket.send(pkt);
166 | if (n > 0 && (size_t)n == pkt.size()) {
167 | counter_packets_send++;
168 | counter_bytes_send += pkt.size();
169 | } else if (n < 0) {
170 | if (errno < 255)
171 | counter_errorcodes[errno]++;
172 | errors++;
173 | } else {
174 | counter_0bytes++;
175 | }
176 | return;
177 | } catch (const UnknownRRType& exp) {
178 | continue;
179 | } catch (const InvalidDNSQuery& exp) {
180 | continue;
181 | }
182 | }
183 | }
184 |
185 | void DNSSenderThread::run()
186 | {
187 | if (!payload)
188 | throw ppl7::NullPointerException("payload not set!");
189 | if (!spoofingEnabled) {
190 | pkt.setSource(sourceip, 0x4567);
191 | }
192 | dnsseccounter = 0;
193 | counter_packets_send = 0;
194 | counter_bytes_send = 0;
195 | counter_0bytes = 0;
196 | errors = 0;
197 | duration = 0.0;
198 | for (int i = 0; i < 255; i++)
199 | counter_errorcodes[i] = 0;
200 | double start = ppl7::GetMicrotime();
201 | if (queryrate > 0) {
202 | runWithRateLimit();
203 | } else {
204 | runWithoutRateLimit();
205 | }
206 | duration = ppl7::GetMicrotime() - start;
207 | waitForTimeout();
208 | }
209 |
210 | void DNSSenderThread::runWithoutRateLimit()
211 | {
212 | double start = ppl7::GetMicrotime();
213 | double end = start + (double)runtime;
214 | double now;
215 | int pc = 0;
216 | while (1) {
217 | sendPacket();
218 | pc++;
219 | if (pc > 10000) {
220 | pc = 0;
221 | if (this->threadShouldStop())
222 | break;
223 | now = ppl7::GetMicrotime();
224 | if (now > end)
225 | break;
226 | }
227 | }
228 | }
229 |
230 | static inline double getNsec()
231 | {
232 | struct timespec ts;
233 | clock_gettime(CLOCK_REALTIME, &ts);
234 | return (double)ts.tv_sec + ((double)ts.tv_nsec / 1000000000.0);
235 | }
236 |
237 | void DNSSenderThread::runWithRateLimit()
238 | {
239 | struct timespec ts;
240 | ppluint64 total_timeslices = runtime * 1000 / (Timeslice * 1000.0);
241 | ppluint64 queries_rest = runtime * queryrate;
242 | ppl7::SockAddr addr = Socket.getSockAddr();
243 | verbose = true;
244 | if (verbose) {
245 | //printf ("qps=%d, runtime=%d\n",queryrate, runtime);
246 | printf("runtime: %d s, timeslice: %0.6f s, total timeslices: %llu, Qpts: %llu, Source: %s:%d\n",
247 | runtime, Timeslice, total_timeslices,
248 | queries_rest / total_timeslices,
249 | (const char*)addr.toIPAddress().toString(), addr.port());
250 | }
251 | double now = getNsec();
252 | double next_timeslice = now;
253 | double next_checktime = now + 0.1;
254 |
255 | double start = ppl7::GetMicrotime();
256 | double end = start + (double)runtime;
257 | double total_idle = 0.0;
258 |
259 | for (ppluint64 z = 0; z < total_timeslices; z++) {
260 | next_timeslice += Timeslice;
261 | ppluint64 timeslices_rest = total_timeslices - z;
262 | ppluint64 queries_per_timeslice = queries_rest / timeslices_rest;
263 | if (timeslices_rest == 1)
264 | queries_per_timeslice = queries_rest;
265 | for (ppluint64 i = 0; i < queries_per_timeslice; i++) {
266 | sendPacket();
267 | }
268 |
269 | queries_rest -= queries_per_timeslice;
270 | while ((now = getNsec()) < next_timeslice) {
271 | if (now < next_timeslice) {
272 | total_idle += next_timeslice - now;
273 | ts.tv_sec = 0;
274 | ts.tv_nsec = (next_timeslice - now) * 1000000000;
275 | nanosleep(&ts, NULL);
276 | }
277 | }
278 | if (now > next_checktime) {
279 | next_checktime = now + 0.1;
280 | if (this->threadShouldStop())
281 | break;
282 | if (ppl7::GetMicrotime() >= end)
283 | break;
284 | //printf ("Zeitscheiben rest: %llu\n", z);
285 | }
286 | }
287 | if (verbose) {
288 | //printf ("total idle: %0.6f\n",total_idle);
289 | }
290 | }
291 |
292 | void DNSSenderThread::waitForTimeout()
293 | {
294 | double start = ppl7::GetMicrotime();
295 | double end = start + (double)timeout;
296 | double now, next_checktime = start + 0.1;
297 | while ((now = ppl7::GetMicrotime()) < end) {
298 | if (now > next_checktime) {
299 | next_checktime = now + 0.1;
300 | if (this->threadShouldStop())
301 | break;
302 | }
303 | ppl7::MSleep(10);
304 | }
305 | }
306 |
307 | ppluint64 DNSSenderThread::getPacketsSend() const
308 | {
309 | return counter_packets_send;
310 | }
311 |
312 | ppluint64 DNSSenderThread::getBytesSend() const
313 | {
314 | return counter_bytes_send;
315 | }
316 |
317 | ppluint64 DNSSenderThread::getErrors() const
318 | {
319 | return errors;
320 | }
321 |
322 | ppluint64 DNSSenderThread::getCounter0Bytes() const
323 | {
324 | return counter_0bytes;
325 | }
326 |
327 | ppluint64 DNSSenderThread::getCounterErrorCode(int err) const
328 | {
329 | if (err < 255)
330 | return counter_errorcodes[err];
331 | return 0;
332 | }
333 |
--------------------------------------------------------------------------------
/src/raw_socket_receiver.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "config.h"
23 |
24 | #include "raw_socket_receiver.h"
25 | #include "query.h"
26 | #include "exceptions.h"
27 |
28 | #define __FAVOR_BSD 1
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | #ifdef __OpenBSD__
39 | #error "Raw socket receiver not implemented for OpenBSD"
40 | #endif
41 | #ifdef __FreeBSD__
42 | #define DNSMETER_USE_BPF 1
43 | #include
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 | #endif
50 |
51 | #pragma pack(push) /* push current alignment to stack */
52 | #pragma pack(1) /* set alignment to 1 byte boundary */
53 | struct ETHER {
54 | unsigned char destination[6];
55 | unsigned char source[6];
56 | unsigned short type;
57 | };
58 | #pragma pack(pop) /* restore original alignment from stack */
59 |
60 | #ifdef DNSMETER_USE_BPF
61 | static int open_bpf()
62 | {
63 | int sd;
64 | for (int i = 0; i < 255; i++) {
65 | ppl7::String Device;
66 | Device.setf("/dev/bpf%d", i);
67 | sd = open((const char*)Device, O_RDWR);
68 | if (sd >= 0) {
69 | return sd;
70 | }
71 | }
72 | ppl7::throwExceptionFromErrno(errno, "Could not create RawReceiverSocket");
73 | return -1;
74 | }
75 |
76 | bool tryAllocZeroCopyBuffer(int sd, struct bpf_zbuf* zbuf, size_t size)
77 | {
78 | zbuf->bz_buflen = size;
79 | zbuf->bz_bufa = malloc(zbuf->bz_buflen);
80 | if (!zbuf->bz_bufa) {
81 | throw ppl7::OutOfMemoryException();
82 | }
83 | zbuf->bz_bufb = malloc(zbuf->bz_buflen);
84 | if (!zbuf->bz_bufb) {
85 | free(zbuf->bz_bufa);
86 | throw ppl7::OutOfMemoryException();
87 | }
88 | memset(zbuf->bz_bufa, 0, zbuf->bz_buflen);
89 | memset(zbuf->bz_bufb, 0, zbuf->bz_buflen);
90 |
91 | if (ioctl(sd, BIOCSETZBUF, zbuf) < 0) {
92 | free(zbuf->bz_bufa);
93 | free(zbuf->bz_bufb);
94 | return false;
95 | }
96 | return true;
97 | }
98 |
99 | void initZeroCopyBuffer(int sd, struct bpf_zbuf* zbuf)
100 | {
101 | unsigned int bufmode = BPF_BUFMODE_ZBUF;
102 | if (ioctl(sd, BIOCSETBUFMODE, &bufmode) < 0) {
103 | ppl7::throwExceptionFromErrno(errno, "BIOCSETBUFMODE with BPF_BUFMODE_ZBUF failed");
104 | }
105 | unsigned int tstype = BPF_T_MICROTIME;
106 | if (ioctl(sd, BIOCSTSTAMP, &tstype) < 0) {
107 | ppl7::throwExceptionFromErrno(errno, "BIOCSTSTAMP");
108 | }
109 | if (tryAllocZeroCopyBuffer(sd, zbuf, 8192))
110 | return;
111 | if (tryAllocZeroCopyBuffer(sd, zbuf, 4096))
112 | return;
113 | throw FailedToInitializePacketfilter("Could not configure ZeroCopy-Buffer (BIOCSETZBUF)");
114 | }
115 |
116 | void initBufferedMode(int sd, unsigned int buflen)
117 | {
118 | unsigned int bufmode = BPF_BUFMODE_BUFFER;
119 | if (ioctl(sd, BIOCSETBUFMODE, &bufmode) < 0) {
120 | ppl7::throwExceptionFromErrno(errno, "BIOCSETBUFMODE with BPF_BUFMODE_BUFFER failed");
121 | }
122 | if (ioctl(sd, BIOCSBLEN, &buflen) < 0) {
123 | ppl7::throwExceptionFromErrno(errno, "BIOCSBLEN failed");
124 | }
125 | }
126 |
127 | #endif
128 |
129 | RawSocketReceiver::Counter::Counter()
130 | {
131 | num_pkgs = 0;
132 | bytes_rcv = 0;
133 | truncated = 0;
134 | for (int i = 0; i < 15; i++)
135 | rcodes[i] = 0;
136 | rtt_total = 0.0f;
137 | rtt_min = 0.0f;
138 | rtt_max = 0.0f;
139 | }
140 |
141 | void RawSocketReceiver::Counter::clear()
142 | {
143 | num_pkgs = 0;
144 | bytes_rcv = 0;
145 | truncated = 0;
146 | for (int i = 0; i < 15; i++)
147 | rcodes[i] = 0;
148 | rtt_total = 0.0f;
149 | rtt_min = 0.0f;
150 | rtt_max = 0.0f;
151 | }
152 |
153 | RawSocketReceiver::RawSocketReceiver()
154 | {
155 | SourceIP.set("0.0.0.0");
156 | SourcePort = 0;
157 | buflen = 4096;
158 | sd = -1;
159 | buffer = NULL;
160 | #ifdef DNSMETER_USE_BPF
161 | useZeroCopyBuffer = false;
162 | sd = open_bpf();
163 | buffer = (unsigned char*)malloc(sizeof(struct bpf_zbuf));
164 | if (!buffer) {
165 | close(sd);
166 | throw ppl7::OutOfMemoryException();
167 | }
168 | struct bpf_zbuf* zbuf = (struct bpf_zbuf*)buffer;
169 |
170 | try {
171 | initZeroCopyBuffer(sd, zbuf);
172 | useZeroCopyBuffer = true;
173 | buflen = zbuf->bz_buflen;
174 | printf("INFO: using fast bpf zero copy buffer for packet capturing\n");
175 | return;
176 | } catch (const ppl7::Exception& ex) {
177 | useZeroCopyBuffer = false;
178 | free(buffer);
179 | }
180 | buflen = 8192;
181 | buffer = (unsigned char*)malloc(buflen);
182 | if (!buffer) {
183 | close(sd);
184 | throw ppl7::OutOfMemoryException();
185 | }
186 | try {
187 | initBufferedMode(sd, buflen);
188 | printf("INFO: using normal bpf buffered mode for packet capturing\n");
189 | int ret = fcntl(sd, F_SETFL, fcntl(sd, F_GETFL, 0) | O_NONBLOCK); // NON-Blocking
190 | if (ret < 0)
191 | ppl7::throwExceptionFromErrno(errno, "Could not set bpf into non blocking mode");
192 |
193 | } catch (const ppl7::Exception& ex) {
194 | free(buffer);
195 | close(sd);
196 | throw;
197 | }
198 |
199 | #else
200 | buffer = (unsigned char*)malloc(buflen);
201 | if (!buffer)
202 | throw ppl7::OutOfMemoryException();
203 | if ((sd = socket(AF_PACKET, SOCK_RAW, htons(0x0800))) == -1) {
204 | int e = errno;
205 | free(buffer);
206 | ppl7::throwExceptionFromErrno(e, "Could not create RawReceiverSocket");
207 | }
208 | int ret = fcntl(sd, F_SETFL, fcntl(sd, F_GETFL, 0) | O_NONBLOCK); // NON-Blocking
209 | if (ret < 0) {
210 | int e = errno;
211 | close(sd);
212 | free(buffer);
213 | ppl7::throwExceptionFromErrno(e, "Could not set bpf into non blocking mode");
214 | }
215 |
216 | #endif
217 | }
218 |
219 | RawSocketReceiver::~RawSocketReceiver()
220 | {
221 | close(sd);
222 | #ifdef DNSMETER_USE_BPF
223 | if (useZeroCopyBuffer) {
224 | struct bpf_zbuf* zbuf = (struct bpf_zbuf*)buffer;
225 | free(zbuf->bz_bufa);
226 | free(zbuf->bz_bufb);
227 | }
228 | #endif
229 | free(buffer);
230 | }
231 |
232 | void RawSocketReceiver::initInterface(const ppl7::String& Device)
233 | {
234 | #ifdef DNSMETER_USE_BPF
235 | struct ifreq ifreq;
236 | strcpy((char*)ifreq.ifr_name, (const char*)Device);
237 | if (ioctl(sd, BIOCSETIF, &ifreq) < 0) {
238 | ppl7::throwExceptionFromErrno(errno, "Could not bind RawReceiverSocket on interface (BIOCSETIF)");
239 | }
240 | unsigned int promiscuous_mode = 1;
241 | if (ioctl(sd, BIOCPROMISC, &promiscuous_mode) < 0) {
242 | ppl7::throwExceptionFromErrno(errno, "Could not set Interface into promiscuous mode (BIOCPROMISC)");
243 | }
244 | #endif
245 | }
246 |
247 | void RawSocketReceiver::setSource(const ppl7::IPAddress& ip_addr, int port)
248 | {
249 | SourceIP = ip_addr;
250 | SourcePort = htons(port);
251 | #ifdef DNSMETER_USE_BPF
252 | // Install packet filter in bpf
253 | int sip = htonl(*(int*)SourceIP.addr());
254 | struct bpf_insn insns[] = {
255 | // load halfword at position 12 from packet into register
256 | BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
257 | // is it 0x800? if no, jump over 5 instructions, else jump over 0
258 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0800, 0, 7),
259 | // source ip
260 | BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 26),
261 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (unsigned int)sip, 0, 5),
262 |
263 | // udp?
264 | BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23),
265 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 17, 0, 3),
266 |
267 | // source port
268 | BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 34),
269 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (unsigned int)port, 0, 1),
270 |
271 | /* if we reach here, return -1 which will allow the packet to be read */
272 | BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
273 | /* if we reach here, return 0 which will ignore the packet */
274 | BPF_STMT(BPF_RET + BPF_K, 0),
275 | };
276 | struct bpf_program bpf_program = {
277 | 10,
278 | (struct bpf_insn*)&insns
279 | };
280 | if (ioctl(sd, BIOCSETF, (struct bpf_program*)&bpf_program) < 0) {
281 | throw FailedToInitializePacketfilter();
282 | }
283 | #endif
284 | }
285 |
286 | bool RawSocketReceiver::socketReady()
287 | {
288 | // #ifdef DNSMETER_USE_BPF
289 | // if (useZeroCopyBuffer) return true;
290 | // #endif
291 | fd_set rset;
292 | struct timeval timeout;
293 | timeout.tv_sec = 0;
294 | timeout.tv_usec = 100;
295 | FD_ZERO(&rset);
296 | FD_SET(sd, &rset); // Wir wollen nur prüfen, ob wir lesen können
297 | int ret = select(sd + 1, &rset, NULL, NULL, &timeout);
298 | if (ret < 0)
299 | return false;
300 | if (FD_ISSET(sd, &rset)) {
301 | return true;
302 | }
303 | return false;
304 | }
305 |
306 | static void count_packet(RawSocketReceiver::Counter& counter, unsigned char* buffer, size_t size)
307 | {
308 | counter.num_pkgs++;
309 | counter.bytes_rcv += size;
310 | struct DNS_HEADER* dns = (struct DNS_HEADER*)(buffer + 14 + sizeof(struct ip) + sizeof(struct udphdr));
311 | double rd = getQueryRTT(ntohs(dns->id));
312 | counter.rtt_total += rd;
313 | if (rd < counter.rtt_min || counter.rtt_min == 0)
314 | counter.rtt_min = rd;
315 | if (rd > counter.rtt_max)
316 | counter.rtt_max = rd;
317 | if (dns->rcode < 16)
318 | counter.rcodes[dns->rcode]++;
319 | if (dns->tc)
320 | counter.truncated++;
321 | }
322 |
323 | #ifdef DNSMETER_USE_BPF
324 | /*
325 | * Return ownership of a buffer to the kernel for reuse.
326 | */
327 | static void buffer_acknowledge(struct bpf_zbuf_header* bzh)
328 | {
329 | atomic_store_rel_int(&bzh->bzh_user_gen, bzh->bzh_kernel_gen);
330 | }
331 |
332 | static int buffer_check(struct bpf_zbuf_header* bzh)
333 | {
334 | return (bzh->bzh_user_gen != atomic_load_acq_int(&bzh->bzh_kernel_gen));
335 | }
336 |
337 | static void read_buffer(unsigned char* ptr, size_t size, RawSocketReceiver::Counter& counter)
338 | {
339 | size_t done = 0;
340 | while (done < size) {
341 | struct bpf_hdr* bpfh = (struct bpf_hdr*)ptr;
342 | if (bpfh->bh_caplen == 0 || bpfh->bh_hdrlen == 0)
343 | break;
344 | size_t chunk_size = BPF_WORDALIGN(bpfh->bh_caplen + bpfh->bh_hdrlen);
345 | count_packet(counter, ptr + bpfh->bh_hdrlen, chunk_size - bpfh->bh_datalen);
346 | ptr += chunk_size;
347 | done += chunk_size;
348 | }
349 | }
350 |
351 | static void read_zbuffer(struct bpf_zbuf_header* zhdr, RawSocketReceiver::Counter& counter)
352 | {
353 | size_t size = zhdr->bzh_kernel_len - sizeof(struct bpf_zbuf_header);
354 | unsigned char* ptr = (unsigned char*)zhdr + sizeof(struct bpf_zbuf_header);
355 | read_buffer(ptr, size, counter);
356 | buffer_acknowledge(zhdr);
357 | }
358 | void RawSocketReceiver::receive(RawSocketReceiver::Counter& counter)
359 | {
360 | if (useZeroCopyBuffer) {
361 | struct bpf_zbuf* zbuf = (struct bpf_zbuf*)buffer;
362 | struct bpf_zbuf_header* zhdr = NULL;
363 | if (buffer_check((struct bpf_zbuf_header*)zbuf->bz_bufa)) {
364 | zhdr = ((struct bpf_zbuf_header*)zbuf->bz_bufa);
365 | read_zbuffer(zhdr, counter);
366 | }
367 | if (buffer_check((struct bpf_zbuf_header*)zbuf->bz_bufb)) {
368 | zhdr = ((struct bpf_zbuf_header*)zbuf->bz_bufb);
369 | read_zbuffer(zhdr, counter);
370 | }
371 | } else {
372 | ssize_t bufused = read(sd, buffer, buflen);
373 | if (bufused < 34)
374 | return;
375 | read_buffer(buffer, bufused, counter);
376 | }
377 | }
378 |
379 | #else
380 | void RawSocketReceiver::receive(Counter& counter)
381 | {
382 | unsigned char* ptr = buffer;
383 | ssize_t bufused = recvfrom(sd, buffer, buflen, 0, NULL, NULL);
384 | if (bufused < 34)
385 | return;
386 | struct ETHER* eth = (struct ETHER*)ptr;
387 | //ppl7::HexDump(ptr,bufused);
388 | //printf ("sizeof ETHER=%d, type=%X\n",sizeof(struct ETHER),eth->type);
389 | if (eth->type != htons(0x0800))
390 | return;
391 | struct ip* iphdr = (struct ip*)(ptr + 14);
392 | if (iphdr->ip_v != 4)
393 | return;
394 | if (iphdr->ip_src.s_addr != *(in_addr_t*)SourceIP.addr())
395 | return;
396 |
397 | struct udphdr* udp = (struct udphdr*)(ptr + 14 + sizeof(struct ip));
398 | if (udp->uh_sport != SourcePort)
399 | return;
400 | count_packet(counter, ptr, bufused);
401 | }
402 | #endif
403 |
--------------------------------------------------------------------------------
/src/system_stat.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "config.h"
23 |
24 | #include "system_stat.h"
25 | #include "exceptions.h"
26 |
27 | #ifdef __linux__
28 | #include
29 | #endif
30 | #include
31 | #include
32 | #include
33 | #ifdef __FreeBSD__
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 | #endif
42 |
43 | // ########################################################### Linux specific
44 | #ifdef __linux__
45 | static void sampleCpuUsage(SystemStat::Cpu& stat)
46 | {
47 | FILE* fp = fopen("/proc/stat", "r");
48 | if (fscanf(fp, "%*s %d %d %d %d %d", &stat.user, &stat.nice, &stat.system, &stat.idle, &stat.iowait) != 5) {
49 | // ignore
50 | }
51 | fclose(fp);
52 | }
53 |
54 | static void sampleSysinfo(SystemStat::Sysinfo& stat)
55 | {
56 | struct sysinfo info;
57 | if (0 != sysinfo(&info)) {
58 | return;
59 | }
60 | stat.uptime = info.uptime;
61 | stat.freeswap = info.freeswap * info.mem_unit;
62 | stat.freeram = info.freeram * info.mem_unit;
63 | stat.bufferram = info.bufferram * info.mem_unit;
64 | stat.totalram = info.totalram * info.mem_unit;
65 | stat.totalswap = info.totalswap * info.mem_unit;
66 | stat.sharedram = info.sharedram * info.mem_unit;
67 | stat.procs = info.procs;
68 | }
69 |
70 | static void sampleNetwork(std::map& interfaces, SystemStat::Interface& total)
71 | {
72 | total.receive.clear();
73 | total.transmit.clear();
74 |
75 | ppl7::String buffer;
76 | ppl7::File ff("/proc/net/dev");
77 | while (!ff.eof()) {
78 | ff.gets(buffer, 2048);
79 | buffer.trim();
80 | ssize_t t = buffer.instr(":");
81 | if (t > 1) {
82 | SystemStat::Interface nif;
83 | nif.Name.set(buffer, t);
84 | buffer.replace("\t", " ");
85 | ppl7::Array tok = ppl7::StrTok(buffer, " ");
86 | nif.receive.bytes = tok[1].toUnsignedLong();
87 | nif.receive.packets = tok[2].toUnsignedLong();
88 | nif.receive.errs = tok[3].toUnsignedLong();
89 | nif.receive.drop = tok[4].toUnsignedLong();
90 |
91 | nif.transmit.bytes = tok[9].toUnsignedLong();
92 | nif.transmit.packets = tok[10].toUnsignedLong();
93 | nif.transmit.errs = tok[11].toUnsignedLong();
94 | nif.transmit.drop = tok[12].toUnsignedLong();
95 |
96 | total.receive.bytes += nif.receive.bytes;
97 | total.receive.packets += nif.receive.packets;
98 | total.receive.errs += nif.receive.errs;
99 | total.receive.drop += nif.receive.drop;
100 |
101 | total.transmit.bytes += nif.transmit.bytes;
102 | total.transmit.packets += nif.transmit.packets;
103 | total.transmit.errs += nif.transmit.errs;
104 | total.transmit.drop += nif.transmit.drop;
105 | interfaces.insert(std::pair(nif.Name, nif));
106 | }
107 | }
108 | }
109 |
110 | // ########################################################### FreeBSD specific
111 | #elif defined __FreeBSD__
112 | static kvm_t* kd = NULL;
113 | #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
114 |
115 | static void
116 | getsysctl(const char* name, void* ptr, size_t len)
117 | {
118 | size_t nlen = len;
119 | if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
120 | throw SystemCallFailed("sysctlbyname(%s...) failed: %s\n", name,
121 | strerror(errno));
122 | }
123 | if (nlen != len) {
124 | throw SystemCallFailed("sysctlbyname(%s...) expected %lu, got %lu\n",
125 | name, (unsigned long)len, (unsigned long)nlen);
126 | }
127 | }
128 |
129 | static void sampleCpuUsage(SystemStat::Cpu& stat)
130 | {
131 | size_t cp_size = sizeof(long) * CPUSTATES * 8;
132 | long* cp_times = (long*)malloc(cp_size);
133 | if (sysctlbyname("kern.cp_time", cp_times, &cp_size, NULL, 0) < 0) {
134 | perror("sysctlbyname");
135 | free(cp_times);
136 | }
137 | stat.user = (int)cp_times[0];
138 | stat.nice = (int)cp_times[1];
139 | stat.system = (int)cp_times[2];
140 | stat.iowait = (int)cp_times[3];
141 | stat.idle = (int)cp_times[4];
142 | }
143 |
144 | static int
145 | swapmode(long* retavail, long* retfree)
146 | {
147 | int n;
148 | int pagesize = getpagesize();
149 | struct kvm_swap swapary[1];
150 |
151 | *retavail = 0;
152 | *retfree = 0;
153 |
154 | #define CONVERT(v) ((quad_t)(v)*pagesize)
155 |
156 | n = kvm_getswapinfo(kd, swapary, 1, 0);
157 | if (n < 0 || swapary[0].ksw_total == 0)
158 | return (0);
159 |
160 | *retavail = CONVERT(swapary[0].ksw_total);
161 | *retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used);
162 |
163 | n = (int)(swapary[0].ksw_used * 100.0 / swapary[0].ksw_total);
164 | return (n);
165 | }
166 |
167 | static void sampleSysinfo(SystemStat::Sysinfo& stat)
168 | {
169 | struct timespec uptime;
170 | int pagesize = getpagesize();
171 | if (clock_gettime(CLOCK_UPTIME, &uptime) == 0)
172 | stat.uptime = uptime.tv_sec;
173 | swapmode(&stat.totalswap, &stat.freeswap);
174 | int tmp;
175 | long tmp_l;
176 | GETSYSCTL("vm.stats.vm.v_free_count", tmp);
177 | stat.freeram = tmp * pagesize;
178 | GETSYSCTL("hw.physmem", tmp_l);
179 | stat.totalram = tmp_l;
180 | }
181 |
182 | static void sampleNetwork(std::map& interfaces, SystemStat::Interface& total)
183 | {
184 | total.receive.clear();
185 | total.transmit.clear();
186 |
187 | #define IFA_STAT(s) (((struct if_data*)ifa->ifa_data)->ifi_##s)
188 |
189 | struct ifaddrs* ifap = NULL;
190 | if (getifaddrs(&ifap) != 0) {
191 | throw SystemCallFailed("FreeBSD, getifaddrs: %s", strerror(errno));
192 | }
193 | for (struct ifaddrs* ifa = ifap; ifa; ifa = ifa->ifa_next) {
194 | if (ifa->ifa_addr->sa_family != AF_LINK)
195 | continue;
196 | SystemStat::Interface nif;
197 | nif.Name.setf("%s", ifa->ifa_name);
198 |
199 | nif.receive.bytes = IFA_STAT(ibytes);
200 | nif.receive.packets = IFA_STAT(ipackets);
201 | nif.receive.errs = IFA_STAT(ierrors);
202 | nif.receive.drop = IFA_STAT(iqdrops);
203 |
204 | nif.transmit.bytes = IFA_STAT(obytes);
205 | nif.transmit.packets = IFA_STAT(opackets);
206 | nif.transmit.errs = IFA_STAT(oerrors);
207 | nif.transmit.drop = IFA_STAT(oqdrops);
208 |
209 | total.receive.bytes += nif.receive.bytes;
210 | total.receive.packets += nif.receive.packets;
211 | total.receive.errs += nif.receive.errs;
212 | total.receive.drop += nif.receive.drop;
213 |
214 | total.transmit.bytes += nif.transmit.bytes;
215 | total.transmit.packets += nif.transmit.packets;
216 | total.transmit.errs += nif.transmit.errs;
217 | total.transmit.drop += nif.transmit.drop;
218 | interfaces.insert(std::pair(nif.Name, nif));
219 | }
220 | freeifaddrs(ifap);
221 | }
222 |
223 | static void exit_kvm()
224 | {
225 | if (kd)
226 | kvm_close(kd);
227 | }
228 |
229 | #endif
230 |
231 | void sampleSensorData(SystemStat& stat)
232 | {
233 | #ifdef __FreeBSD__
234 | if (!kd) {
235 | kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
236 | if (!kd)
237 | throw KernelAccessFailed("FreeBSD kvm_open failed");
238 | atexit(exit_kvm);
239 | }
240 | #endif
241 | stat.sampleTime = ppl7::GetMicrotime();
242 | sampleCpuUsage(stat.cpu);
243 | sampleSysinfo(stat.sysinfo);
244 | sampleNetwork(stat.interfaces, stat.net_total);
245 | }
246 |
247 | double SystemStat::Cpu::getUsage(const SystemStat::Cpu& sample1, const SystemStat::Cpu& sample2)
248 | {
249 | return 100.0 * (double)((sample2.user + sample2.nice + sample2.system) - (sample1.user + sample1.nice + sample1.system)) / (double)((sample2.user + sample2.nice + sample2.system + sample2.idle) - (sample1.user + sample1.nice + sample1.system + sample1.idle));
250 | }
251 |
252 | static unsigned long delta_with_overflow(unsigned long sample1, unsigned long sample2)
253 | {
254 | if (sample2 >= sample1)
255 | return sample2 - sample1;
256 | return ULONG_MAX - sample1 + sample2;
257 | }
258 |
259 | SystemStat::Network SystemStat::Network::getDelta(const SystemStat::Network& sample1, const SystemStat::Network& sample2)
260 | {
261 | return SystemStat::Network(delta_with_overflow(sample1.bytes, sample2.bytes),
262 | delta_with_overflow(sample1.packets, sample2.packets),
263 | delta_with_overflow(sample1.errs, sample2.errs),
264 | delta_with_overflow(sample1.drop, sample2.drop));
265 | }
266 |
267 | void SystemStat::exportToArray(ppl7::AssocArray& data) const
268 | {
269 | data.setf("sampleTime", "%0.6f", sampleTime);
270 | data.setf("net_total/receive/bytes", "%lu", net_total.receive.bytes);
271 | data.setf("net_total/receive/packets", "%lu", net_total.receive.packets);
272 | data.setf("net_total/receive/errs", "%lu", net_total.receive.errs);
273 | data.setf("net_total/receive/drop", "%lu", net_total.receive.drop);
274 | data.setf("net_total/transmit/bytes", "%lu", net_total.transmit.bytes);
275 | data.setf("net_total/transmit/packets", "%lu", net_total.transmit.packets);
276 | data.setf("net_total/transmit/errs", "%lu", net_total.transmit.errs);
277 | data.setf("net_total/transmit/drop", "%lu", net_total.transmit.drop);
278 | std::map::const_iterator it;
279 | for (it = interfaces.begin(); it != interfaces.end(); ++it) {
280 | ppl7::AssocArray d;
281 | const SystemStat::Interface& nif = it->second;
282 | d.setf("receive/bytes", "%lu", nif.receive.bytes);
283 | d.setf("receive/packets", "%lu", nif.receive.packets);
284 | d.setf("receive/errs", "%lu", nif.receive.errs);
285 | d.setf("receive/drop", "%lu", nif.receive.drop);
286 | d.setf("transmit/bytes", "%lu", nif.transmit.bytes);
287 | d.setf("transmit/packets", "%lu", nif.transmit.packets);
288 | d.setf("transmit/errs", "%lu", nif.transmit.errs);
289 | d.setf("transmit/drop", "%lu", nif.transmit.drop);
290 | d.set("name", nif.Name);
291 | ppl7::String key;
292 | key.setf("interface/%s", (const char*)nif.Name);
293 | data.set(key, d);
294 | }
295 |
296 | data.setf("cpu/user", "%d", cpu.user);
297 | data.setf("cpu/nice", "%d", cpu.nice);
298 | data.setf("cpu/system", "%d", cpu.system);
299 | data.setf("cpu/idle", "%d", cpu.idle);
300 | data.setf("cpu/iowait", "%d", cpu.iowait);
301 |
302 | data.setf("sysinfo/uptime", "%ld", sysinfo.uptime);
303 | data.setf("sysinfo/freeswap", "%ld", sysinfo.freeswap);
304 | data.setf("sysinfo/totalswap", "%ld", sysinfo.totalswap);
305 | data.setf("sysinfo/freeram", "%ld", sysinfo.freeram);
306 | data.setf("sysinfo/bufferram", "%ld", sysinfo.bufferram);
307 | data.setf("sysinfo/totalram", "%ld", sysinfo.totalram);
308 | data.setf("sysinfo/sharedram", "%ld", sysinfo.sharedram);
309 | data.setf("sysinfo/procs", "%d", sysinfo.procs);
310 | }
311 |
312 | void SystemStat::importFromArray(const ppl7::AssocArray& data)
313 | {
314 | sampleTime = data.getString("sampleTime").toDouble();
315 | net_total.receive.bytes = data.getString("net_total/receive/bytes").toUnsignedLong();
316 | net_total.receive.packets = data.getString("net_total/receive/packets").toUnsignedLong();
317 | net_total.receive.errs = data.getString("net_total/receive/errs").toUnsignedLong();
318 | net_total.receive.drop = data.getString("net_total/receive/drop").toUnsignedLong();
319 | net_total.transmit.bytes = data.getString("net_total/transmit/bytes").toUnsignedLong();
320 | net_total.transmit.packets = data.getString("net_total/transmit/packets").toUnsignedLong();
321 | net_total.transmit.errs = data.getString("net_total/transmit/errs").toUnsignedLong();
322 | net_total.transmit.drop = data.getString("net_total/transmit/drop").toUnsignedLong();
323 |
324 | const ppl7::AssocArray& data_if_list = data.getAssocArray("interface");
325 | ppl7::AssocArray::Iterator it;
326 | data_if_list.reset(it);
327 | while (data_if_list.getNext(it)) {
328 | Interface nif;
329 | nif.Name = it.key();
330 | const ppl7::AssocArray& d = it.value().toAssocArray();
331 | nif.receive.bytes = d.getString("receive/bytes").toUnsignedLong();
332 | nif.receive.packets = d.getString("receive/packets").toUnsignedLong();
333 | nif.receive.errs = d.getString("receive/errs").toUnsignedLong();
334 | nif.receive.drop = d.getString("receive/drop").toUnsignedLong();
335 | nif.transmit.bytes = d.getString("transmit/bytes").toUnsignedLong();
336 | nif.transmit.packets = d.getString("transmit/packets").toUnsignedLong();
337 | nif.transmit.errs = d.getString("transmit/errs").toUnsignedLong();
338 | nif.transmit.drop = d.getString("transmit/drop").toUnsignedLong();
339 | interfaces.insert(std::pair(nif.Name, nif));
340 | }
341 | cpu.user = data.getString("cpu/user").toInt();
342 | cpu.nice = data.getString("cpu/nice").toInt();
343 | cpu.system = data.getString("cpu/system").toInt();
344 | cpu.idle = data.getString("cpu/idle").toInt();
345 | cpu.iowait = data.getString("cpu/iowait").toInt();
346 |
347 | sysinfo.uptime = data.getString("sysinfo/uptime").toLong();
348 | sysinfo.freeswap = data.getString("sysinfo/freeswap").toLong();
349 | sysinfo.totalswap = data.getString("sysinfo/totalswap").toLong();
350 | sysinfo.freeram = data.getString("sysinfo/freeram").toLong();
351 | sysinfo.bufferram = data.getString("sysinfo/bufferram").toLong();
352 | sysinfo.totalram = data.getString("sysinfo/totalram").toLong();
353 | sysinfo.sharedram = data.getString("sysinfo/sharedram").toLong();
354 | sysinfo.procs = data.getString("sysinfo/procs").toInt();
355 | }
356 |
357 | void SystemStat::print() const
358 | {
359 | ppl7::AssocArray a;
360 | exportToArray(a);
361 | a.list();
362 | }
363 |
--------------------------------------------------------------------------------
/src/Makefile.am:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2019-2021, OARC, Inc.
2 | # Copyright (c) 2019, DENIC eG
3 | # All rights reserved.
4 | #
5 | # This file is part of dnsmeter.
6 | #
7 | # dnsmeter is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # dnsmeter is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with dnsmeter. If not, see .
19 |
20 | MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
21 | DISTCLEANFILES = $(srcdir)/pplib/include/ppl7-config.h \
22 | $(srcdir)/pplib/release/libppl7.a
23 | CLEANFILES = dnsmeter.1 *.gcda *.gcno *.gcov
24 |
25 | SUBDIRS = test
26 |
27 | AM_CXXFLAGS = -I$(srcdir) \
28 | -I$(top_srcdir) \
29 | -I$(srcdir)/pplib/include \
30 | $(PTHREAD_CFLAGS) $(ICONV_CFLAGS)
31 |
32 | bin_PROGRAMS = dnsmeter
33 |
34 | dnsmeter_SOURCES = dns_receiver_thread.cpp dns_sender.cpp \
35 | dns_sender_thread.cpp main.cpp packet.cpp payload_file.cpp query.cpp \
36 | raw_socket_receiver.cpp raw_socket_sender.cpp system_stat.cpp
37 | dist_dnsmeter_SOURCES = dns_receiver_thread.h dns_sender.h \
38 | dns_sender_thread.h exceptions.h packet.h payload_file.h query.h \
39 | raw_socket_receiver.h raw_socket_sender.h system_stat.h
40 | dnsmeter_LDADD = $(PTHREAD_LIBS) $(ICONV_LIBS) \
41 | $(srcdir)/pplib/release/libppl7.a
42 |
43 | BUILT_SOURCES = pplib/include/ppl7-config.h
44 |
45 | pplib/include/ppl7-config.h:
46 | cd "$(srcdir)/pplib" && ./configure --disable-oggtest \
47 | --disable-freetypetest --disable-sdltest --disable-sdlframework \
48 | --without-jpeg --without-libjpegturbo --without-libpng \
49 | --without-libmicrohttpd --without-libmcrypt-prefix \
50 | --without-libtiff --without-libcurl --without-mpg123 \
51 | --without-lame --without-ogg --without-libcdio --without-libiconv-prefix \
52 | --without-imlib --without-mysql --without-postgresql \
53 | --without-sqlite3 --without-libldn --without-nasm
54 |
55 | $(srcdir)/pplib/release/libppl7.a: pplib/include/ppl7-config.h
56 | cd "$(srcdir)/pplib" && make
57 |
58 | man1_MANS = dnsmeter.1
59 |
60 | dnsmeter.1: dnsmeter.1.in Makefile
61 | sed -e 's,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g' \
62 | -e 's,[@]PACKAGE_URL[@],$(PACKAGE_URL),g' \
63 | -e 's,[@]PACKAGE_BUGREPORT[@],$(PACKAGE_BUGREPORT),g' \
64 | < $(srcdir)/dnsmeter.1.in > dnsmeter.1
65 |
66 | if ENABLE_GCOV
67 | gcov-local:
68 | for src in $(dnsmeter_SOURCES); do \
69 | gcov -l -r -s "$(srcdir)" "$$src"; \
70 | done
71 | endif
72 |
73 | EXTRA_DIST = dnsmeter.1.in \
74 | pplib/Makefile.in \
75 | pplib/src/types/ByteArrayPtr.cpp \
76 | pplib/src/types/ByteArray.cpp \
77 | pplib/src/types/Array.cpp \
78 | pplib/src/types/Pointer.cpp \
79 | pplib/src/types/WideString.cpp \
80 | pplib/src/types/AssocArray.cpp \
81 | pplib/src/types/String.cpp \
82 | pplib/src/types/Variant.cpp \
83 | pplib/src/types/DateTime.cpp \
84 | pplib/src/math/crc32.cpp \
85 | pplib/src/math/calc.cpp \
86 | pplib/src/math/md5.cpp \
87 | pplib/src/math/random.cpp \
88 | pplib/src/database/MySQL.cpp \
89 | pplib/src/database/ResultSet.cpp \
90 | pplib/src/database/Database.cpp \
91 | pplib/src/database/PostgreSQL.cpp \
92 | pplib/src/database/DBPool.cpp \
93 | pplib/src/database/DBPoolOfPools.cpp \
94 | pplib/src/database/Sqlite3.cpp \
95 | pplib/src/audio/AudioCD.cpp \
96 | pplib/src/audio/AudioEncoder_MP3.cpp \
97 | pplib/src/audio/AudioDecoder_Ogg.cpp \
98 | pplib/src/audio/AudioInfo.cpp \
99 | pplib/src/audio/Cddb.cpp \
100 | pplib/src/audio/AudioDecoder_MP3.cpp \
101 | pplib/src/audio/AudioDecoder_Aiff.cpp \
102 | pplib/src/audio/AudioEncoder_Wave.cpp \
103 | pplib/src/audio/Icecast.cpp \
104 | pplib/src/audio/AudioEncoder_Ogg.cpp \
105 | pplib/src/audio/ID3Tag.cpp \
106 | pplib/src/audio/AudioDecoder_Wave.cpp \
107 | pplib/src/audio/Mp3.cpp \
108 | pplib/src/audio/AudioEncoder_Aiff.cpp \
109 | pplib/src/toolkit/Divider.cpp \
110 | pplib/src/toolkit/WindowManager.cpp \
111 | pplib/src/toolkit/Window.cpp \
112 | pplib/src/toolkit/LineInput.cpp \
113 | pplib/src/toolkit/WindowManager_SDL2.cpp \
114 | pplib/src/toolkit/Layout.cpp \
115 | pplib/src/toolkit/Widget.cpp \
116 | pplib/src/toolkit/Surface.cpp \
117 | pplib/src/toolkit/Frame.cpp \
118 | pplib/src/toolkit/Label.cpp \
119 | pplib/src/toolkit/Button.cpp \
120 | pplib/src/toolkit/Event.cpp \
121 | pplib/src/asm/common.asm \
122 | pplib/src/asm/colors.asm \
123 | pplib/src/asm/pixel.asm \
124 | pplib/src/asm/chromakey.asm \
125 | pplib/src/asm/cpu.asm \
126 | pplib/src/asm/blt_blend.asm \
127 | pplib/src/asm/rect.asm \
128 | pplib/src/asm/fonts.asm \
129 | pplib/src/asm/blt.asm \
130 | pplib/src/internet/WikiParser.cpp \
131 | pplib/src/internet/Webserver.cpp \
132 | pplib/src/internet/ipaddress.cpp \
133 | pplib/src/internet/sockaddr.cpp \
134 | pplib/src/internet/resolver.cpp \
135 | pplib/src/internet/UDPSocket.cpp \
136 | pplib/src/internet/ipnetwork.cpp \
137 | pplib/src/internet/curl.cpp \
138 | pplib/src/internet/SocketMessage.cpp \
139 | pplib/src/internet/inet_functions.cpp \
140 | pplib/src/internet/openssl.cpp \
141 | pplib/src/internet/TCPSocket.cpp \
142 | pplib/src/crypto/Digest.cpp \
143 | pplib/src/crypto/Crypt.cpp \
144 | pplib/src/crypto/MCrypt.cpp \
145 | pplib/src/core/Signal.cpp \
146 | pplib/src/core/Compat.cpp \
147 | pplib/src/core/Mutex.cpp \
148 | pplib/src/core/ThreadPool.cpp \
149 | pplib/src/core/Functions.cpp \
150 | pplib/src/core/MemoryGroup.cpp \
151 | pplib/src/core/MemFile.cpp \
152 | pplib/src/core/StringFunctions.cpp \
153 | pplib/src/core/Dir.cpp \
154 | pplib/src/core/File.cpp \
155 | pplib/src/core/ConfigParser.cpp \
156 | pplib/src/core/DirEntry.cpp \
157 | pplib/src/core/Resourcen.cpp \
158 | pplib/src/core/Exceptions.cpp \
159 | pplib/src/core/FileObject.cpp \
160 | pplib/src/core/PerlHelper.cpp \
161 | pplib/src/core/Json.cpp \
162 | pplib/src/core/Iconv.cpp \
163 | pplib/src/core/AVLTree.cpp \
164 | pplib/src/core/Logger.cpp \
165 | pplib/src/core/Threads.cpp \
166 | pplib/src/core/PythonHelper.cpp \
167 | pplib/src/core/Compression.cpp \
168 | pplib/src/core/Time.cpp \
169 | pplib/src/core/cpu.cpp \
170 | pplib/src/core/MemoryHeap.cpp \
171 | pplib/src/core/PFPFile.cpp \
172 | pplib/src/core/Resource.cpp \
173 | pplib/src/core/GzFile.cpp \
174 | pplib/src/grafix/Point.cpp \
175 | pplib/src/grafix/ImageFilter_PPM.cpp \
176 | pplib/src/grafix/Font5.cpp \
177 | pplib/src/grafix/ImageFilter_JPEG.cpp \
178 | pplib/src/grafix/Rect.cpp \
179 | pplib/src/grafix/DrawableBlit.cpp \
180 | pplib/src/grafix/Point3D.cpp \
181 | pplib/src/grafix/RGBFormat.cpp \
182 | pplib/src/grafix/ImageFilter_GIF.cpp \
183 | pplib/src/grafix/Fonts.cpp \
184 | pplib/src/grafix/ImageFilter_TGA.cpp \
185 | pplib/src/grafix/ImageFilter_PNG.cpp \
186 | pplib/src/grafix/FontFreeType.cpp \
187 | pplib/src/grafix/Grafix.cpp \
188 | pplib/src/grafix/Font6.cpp \
189 | pplib/src/grafix/DrawablePixel.cpp \
190 | pplib/src/grafix/ImageFilter_BMP.cpp \
191 | pplib/src/grafix/Sprite.cpp \
192 | pplib/src/grafix/ImageFilter_TIFF.cpp \
193 | pplib/src/grafix/Size.cpp \
194 | pplib/src/grafix/ImageList.cpp \
195 | pplib/src/grafix/DrawableLines.cpp \
196 | pplib/src/grafix/DrawableColor.cpp \
197 | pplib/src/grafix/DrawableShapes.cpp \
198 | pplib/src/grafix/Image.cpp \
199 | pplib/src/grafix/ImageFilter.cpp \
200 | pplib/src/grafix/ImageFilter_ImageMagick.cpp \
201 | pplib/src/grafix/Font4.cpp \
202 | pplib/src/grafix/Drawable.cpp \
203 | pplib/src/grafix/Color.cpp \
204 | pplib/genConfigure \
205 | pplib/genMakefile.in \
206 | pplib/aclocal.m4 \
207 | pplib/conf.sh \
208 | pplib/include/crypto.h \
209 | pplib/include/ppl7-ppl6compat.h \
210 | pplib/include/ppl7.h \
211 | pplib/include/ppl7-tk.h \
212 | pplib/include/ppl7-visualc-config.h \
213 | pplib/include/ppl7-config.h.in \
214 | pplib/include/config.h.in \
215 | pplib/include/ppl7-inet.h \
216 | pplib/include/ppl7-audio.h \
217 | pplib/include/threads.h \
218 | pplib/include/ppl7-grafix.h \
219 | pplib/include/socket.h \
220 | pplib/include/ppl7-crypto.h \
221 | pplib/include/prolog.h \
222 | pplib/include/ppl7-types.h \
223 | pplib/include/ppl7-algorithms.h \
224 | pplib/include/ppl7-exceptions.h \
225 | pplib/include/ppl7-db.h \
226 | pplib/include/compat.h \
227 | pplib/tests/Makefile.in \
228 | pplib/tests/src/toolkit.h \
229 | pplib/tests/src/stringspeed.cpp \
230 | pplib/tests/src/database/db_mysql.cpp \
231 | pplib/tests/src/database/db_sqlite.cpp \
232 | pplib/tests/src/database/db_postgres.cpp \
233 | pplib/tests/src/audio/id3tag.cpp \
234 | pplib/tests/src/audio/audio_decoder_aiff.cpp \
235 | pplib/tests/src/audio/audio_decoder_mp3.cpp \
236 | pplib/tests/src/audio/audio_encoder_mp3.cpp \
237 | pplib/tests/src/audio/audioinfo.cpp \
238 | pplib/tests/src/audio/audio_encoder_aiff.cpp \
239 | pplib/tests/src/audio/audio_encoder_wave.cpp \
240 | pplib/tests/src/audio/audio_decoder_wave.cpp \
241 | pplib/tests/src/ppl6/strings.cpp \
242 | pplib/tests/src/ppl6/assocarray.cpp \
243 | pplib/tests/src/crypto/mcrypt.cpp \
244 | pplib/tests/src/crypto/crypto.cpp \
245 | pplib/tests/src/crypto/digest.cpp \
246 | pplib/tests/src/wordlist.cpp \
247 | pplib/tests/src/core/stringfunctions.cpp \
248 | pplib/tests/src/core/iconv.cpp \
249 | pplib/tests/src/core/functions.cpp \
250 | pplib/tests/src/core/json.cpp \
251 | pplib/tests/src/core/filestatic.cpp \
252 | pplib/tests/src/core/strings.cpp \
253 | pplib/tests/src/core/gzfile.cpp \
254 | pplib/tests/src/core/pythonhelper.cpp \
255 | pplib/tests/src/core/memoryheap.cpp \
256 | pplib/tests/src/core/avltree.cpp \
257 | pplib/tests/src/core/variant.cpp \
258 | pplib/tests/src/core/pointer.cpp \
259 | pplib/tests/src/core/math.cpp \
260 | pplib/tests/src/core/dir.cpp \
261 | pplib/tests/src/core/configparser.cpp \
262 | pplib/tests/src/core/time.cpp \
263 | pplib/tests/src/core/bytearray.cpp \
264 | pplib/tests/src/core/datetime.cpp \
265 | pplib/tests/src/core/memorygroup.cpp \
266 | pplib/tests/src/core/bytearrayptr.cpp \
267 | pplib/tests/src/core/widestrings.cpp \
268 | pplib/tests/src/core/array.cpp \
269 | pplib/tests/src/core/perlhelper.cpp \
270 | pplib/tests/src/core/file.cpp \
271 | pplib/tests/src/core/logger.cpp \
272 | pplib/tests/src/core/assocarray.cpp \
273 | pplib/tests/src/core/list.cpp \
274 | pplib/tests/src/loggertest.cpp \
275 | pplib/tests/src/grafix/grafix_image.cpp \
276 | pplib/tests/src/grafix/grafix_rect.cpp \
277 | pplib/tests/src/grafix/grafix_imagefilter.cpp \
278 | pplib/tests/src/grafix/grafix_size.cpp \
279 | pplib/tests/src/grafix/grafix_font.cpp \
280 | pplib/tests/src/grafix/grafix_rgbformat.cpp \
281 | pplib/tests/src/grafix/grafix_point3d.cpp \
282 | pplib/tests/src/grafix/grafix_point.cpp \
283 | pplib/tests/src/grafix/grafix.cpp \
284 | pplib/tests/src/grafix/grafix_color.cpp \
285 | pplib/tests/src/grafix/grafix_drawable.cpp \
286 | pplib/tests/src/gfxreftest.cpp \
287 | pplib/tests/src/toolkit.cpp \
288 | pplib/tests/src/textsnippets.cpp \
289 | pplib/tests/src/main.cpp \
290 | pplib/tests/src/threadtest.cpp \
291 | pplib/tests/src/inet/tcpsocket.cpp \
292 | pplib/tests/src/inet/ipaddress.cpp \
293 | pplib/tests/src/inet/wikiparser.cpp \
294 | pplib/tests/src/inet/sockaddr.cpp \
295 | pplib/tests/src/inet/resolver.cpp \
296 | pplib/tests/src/inet/inet.cpp \
297 | pplib/tests/src/inet/ipnetwork.cpp \
298 | pplib/tests/create_postgres_db.sh \
299 | pplib/tests/valgrind.suppressions \
300 | pplib/tests/gcovr \
301 | pplib/tests/test.conf \
302 | pplib/tests/ppl7-tests.h \
303 | pplib/tests/testdata/test_192cbr_taggedWithCover.mp3 \
304 | pplib/tests/testdata/test_192vbr.mp3 \
305 | pplib/tests/testdata/unittest.png \
306 | pplib/tests/testdata/ppl7-icon-64x64.png \
307 | pplib/tests/testdata/test_44kHz_tagged.wav \
308 | pplib/tests/testdata/test.pcx \
309 | pplib/tests/testdata/unicodeUSASCII.txt \
310 | pplib/tests/testdata/test-pal-trans.png \
311 | pplib/tests/testdata/fonts/liberationsans8.fnt5 \
312 | pplib/tests/testdata/fonts/LiberationSans-Bold.ttf \
313 | pplib/tests/testdata/fonts/freesans4.fnt5 \
314 | pplib/tests/testdata/fonts/segoeui4.fnt5 \
315 | pplib/tests/testdata/filenameUSASCII.txt \
316 | pplib/tests/testdata/database/postgresql.sql \
317 | pplib/tests/testdata/database/mysql.sql \
318 | pplib/tests/testdata/database/sqlite3.sql \
319 | pplib/tests/testdata/test_192cbr_tagged.mp3 \
320 | pplib/tests/testdata/test.tga \
321 | pplib/tests/testdata/test.png \
322 | pplib/tests/testdata/jsontest2.json \
323 | pplib/tests/testdata/jsontest4.json \
324 | pplib/tests/testdata/compression.txt \
325 | pplib/tests/testdata/mpg123.h \
326 | pplib/tests/testdata/test.gif \
327 | pplib/tests/testdata/cover.jpg \
328 | pplib/tests/testdata/unittest.bmp \
329 | pplib/tests/testdata/screenshot1.png \
330 | pplib/tests/testdata/lame.h \
331 | pplib/tests/testdata/example.conf \
332 | pplib/tests/testdata/test.tif \
333 | pplib/tests/testdata/dirwalk/testfile.txt \
334 | pplib/tests/testdata/dirwalk/zfile.txt \
335 | pplib/tests/testdata/dirwalk/file1.txt \
336 | pplib/tests/testdata/dirwalk/LICENSE.TXT \
337 | pplib/tests/testdata/dirwalk/file3.txt \
338 | pplib/tests/testdata/dirwalk/file4äöü.txt \
339 | pplib/tests/testdata/dirwalk/afile.txt \
340 | pplib/tests/testdata/dirwalk/file2.txt \
341 | pplib/tests/testdata/test.jpg \
342 | pplib/tests/testdata/reference.png \
343 | pplib/tests/testdata/lame_API.txt \
344 | pplib/tests/testdata/filenameUTF8äöü.txt \
345 | pplib/tests/testdata/tags_at_eof.aiff \
346 | pplib/tests/testdata/test_44kHz.aiff \
347 | pplib/tests/testdata/test_44kHz_tagged.aiff \
348 | pplib/tests/testdata/compression.txt.gz \
349 | pplib/tests/testdata/test_44kHz_taggedWithCover.aiff \
350 | pplib/tests/testdata/test_192cbr.mp3 \
351 | pplib/tests/testdata/test_44kHz.wav \
352 | pplib/tests/testdata/test.ppm \
353 | pplib/tests/testdata/jsontest1.json \
354 | pplib/tests/testdata/unicodeUtf8äöü.txt \
355 | pplib/tests/testdata/jsontest3.json \
356 | pplib/tests/testdata/test_320cbr.mp3 \
357 | pplib/tests/testdata/test.bmp \
358 | pplib/tests/testdata/test-pal.png \
359 | pplib/LICENSE.TXT \
360 | pplib/configure \
361 | pplib/autoconf/iconv.m4 \
362 | pplib/autoconf/imlib.m4 \
363 | pplib/autoconf/libidn.m4 \
364 | pplib/autoconf/imagemagick.m4 \
365 | pplib/autoconf/freetds.m4 \
366 | pplib/autoconf/ax_lib_gcrypt.m4 \
367 | pplib/autoconf/checkfuncs.m4 \
368 | pplib/autoconf/libtiff.m4 \
369 | pplib/autoconf/ldns.m4 \
370 | pplib/autoconf/bzip2.m4 \
371 | pplib/autoconf/ax_lib_crypto.m4 \
372 | pplib/autoconf/ax_lib_sqlite3.m4 \
373 | pplib/autoconf/lib-link.m4 \
374 | pplib/autoconf/ax_check_compiler_flags.m4 \
375 | pplib/autoconf/ax_path_lib_pcre.m4 \
376 | pplib/autoconf/nasm.m4 \
377 | pplib/autoconf/missing \
378 | pplib/autoconf/libcdio.m4 \
379 | pplib/autoconf/libjpeg-turbo.m4 \
380 | pplib/autoconf/libmicrohttpd.m4 \
381 | pplib/autoconf/ax_gcc_x86_cpuid.m4 \
382 | pplib/autoconf/ogg.m4 \
383 | pplib/autoconf/compile \
384 | pplib/autoconf/ax_pthread.m4 \
385 | pplib/autoconf/sdl2.m4 \
386 | pplib/autoconf/ax_cxx_compile_stdcxx.m4 \
387 | pplib/autoconf/ax_check_openssl.m4 \
388 | pplib/autoconf/ax_lib_mysql.m4 \
389 | pplib/autoconf/ax_lib_postgresql.m4 \
390 | pplib/autoconf/ax_have_qt.m4 \
391 | pplib/autoconf/ax_gcc_archflag.m4 \
392 | pplib/autoconf/gtest.m4 \
393 | pplib/autoconf/ax_check_zlib.m4 \
394 | pplib/autoconf/shout.m4 \
395 | pplib/autoconf/jpeg.m4 \
396 | pplib/autoconf/libcurl.m4 \
397 | pplib/autoconf/config.rpath \
398 | pplib/autoconf/ax_cc_maxopt.m4 \
399 | pplib/autoconf/freetype.m4 \
400 | pplib/autoconf/install-sh \
401 | pplib/autoconf/config.sub \
402 | pplib/autoconf/lame.m4 \
403 | pplib/autoconf/libbind.m4 \
404 | pplib/autoconf/config.guess \
405 | pplib/autoconf/libidn2.m4 \
406 | pplib/autoconf/png.m4 \
407 | pplib/autoconf/mpg123.m4 \
408 | pplib/autoconf/libmcrypt.m4 \
409 | pplib/autoconf/ax_cxx_compile_stdcxx_11.m4 \
410 | pplib/TODO.TXT \
411 | pplib/docs/threads.dox \
412 | pplib/docs/credits.dox \
413 | pplib/docs/CWikiParser_diagram.png \
414 | pplib/docs/groups.dox \
415 | pplib/docs/formate.dox \
416 | pplib/docs/pcrenote.dox \
417 | pplib/docs/CWStringSetFunctions.dox \
418 | pplib/docs/pregexpr.dox \
419 | pplib/docs/verwendung.dox \
420 | pplib/docs/win32-vc9-clr.png \
421 | pplib/docs/header-bg.png \
422 | pplib/docs/ppl7style.css \
423 | pplib/docs/CDrawable.png \
424 | pplib/docs/Class_Point.png \
425 | pplib/docs/datentypen.dox \
426 | pplib/docs/main.dox \
427 | pplib/docs/DoxygenLayout.xml \
428 | pplib/docs/sprintf.dox \
429 | pplib/docs/strftime.dox \
430 | pplib/docs/examples/nasm.rules \
431 | pplib/docs/examples/db_examples.cpp \
432 | pplib/docs/examples/CThread_ThreadMain.cpp \
433 | pplib/docs/examples/IcecastExample.cpp \
434 | pplib/docs/examples/ppl7.m4 \
435 | pplib/docs/installation.dox \
436 | pplib/docs/gtest.dox \
437 | pplib/docs/sockets.dox \
438 | pplib/docs/icecast_status.png \
439 | pplib/docs/formate/PFPVersion1.dox \
440 | pplib/docs/formate/PFPVersion2.dox \
441 | pplib/docs/formate/SocketMessage.dox \
442 | pplib/docs/formate/PFPVersion3.dox \
443 | pplib/docs/formate/PPLResVersion6.dox \
444 | pplib/docs/structures.dox \
445 | pplib/docs/header.html \
446 | pplib/docs/win32-vc9-rl.png \
447 | pplib/docs/datenbanken.dox \
448 | pplib/Doxyfile \
449 | pplib/configure.ac \
450 | pplib/HISTORY.TXT \
451 | pplib/acinclude.m4 \
452 | pplib/ppl7-config.in \
453 | pplib/resource/ppl7-icon-16x16.png \
454 | pplib/resource/ppl7-icon-64x64.png \
455 | pplib/resource/toolbar.png \
456 | pplib/resource/wikistyle.css \
457 | pplib/resource/liberationsans2.fnt6 \
458 | pplib/resource/resourcen.lst \
459 | pplib/resource/ppl7.ico \
460 | pplib/resource/ppl7-icon-256x256.png \
461 | pplib/resource/ppl7-icon-32x32.png \
462 | pplib/resource/ButtonSymbols.png \
463 | pplib/resource/ppl7-icon-128x128.png \
464 | pplib/resource/ppl7-icon-48x48.png \
465 | pplib/resource/cursor.png \
466 | pplib/resource/makefonts.sh \
467 | pplib/resource/mimetypes.png \
468 | pplib/resource/liberationmono2.fnt6 \
469 | pplib/resource/res.h \
470 | pplib/resource/SymbolsAlpha.png \
471 | pplib/resource/icons.png \
472 | pplib/README.TXT
473 |
--------------------------------------------------------------------------------
/m4/ax_pthread.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # https://www.gnu.org/software/autoconf-archive/ax_pthread.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
8 | #
9 | # DESCRIPTION
10 | #
11 | # This macro figures out how to build C programs using POSIX threads. It
12 | # sets the PTHREAD_LIBS output variable to the threads library and linker
13 | # flags, and the PTHREAD_CFLAGS output variable to any special C compiler
14 | # flags that are needed. (The user can also force certain compiler
15 | # flags/libs to be tested by setting these environment variables.)
16 | #
17 | # Also sets PTHREAD_CC to any special C compiler that is needed for
18 | # multi-threaded programs (defaults to the value of CC otherwise). (This
19 | # is necessary on AIX to use the special cc_r compiler alias.)
20 | #
21 | # NOTE: You are assumed to not only compile your program with these flags,
22 | # but also to link with them as well. For example, you might link with
23 | # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
24 | #
25 | # If you are only building threaded programs, you may wish to use these
26 | # variables in your default LIBS, CFLAGS, and CC:
27 | #
28 | # LIBS="$PTHREAD_LIBS $LIBS"
29 | # CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
30 | # CC="$PTHREAD_CC"
31 | #
32 | # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
33 | # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
34 | # that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
35 | #
36 | # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
37 | # PTHREAD_PRIO_INHERIT symbol is defined when compiling with
38 | # PTHREAD_CFLAGS.
39 | #
40 | # ACTION-IF-FOUND is a list of shell commands to run if a threads library
41 | # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
42 | # is not found. If ACTION-IF-FOUND is not specified, the default action
43 | # will define HAVE_PTHREAD.
44 | #
45 | # Please let the authors know if this macro fails on any platform, or if
46 | # you have any other suggestions or comments. This macro was based on work
47 | # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
48 | # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
49 | # Alejandro Forero Cuervo to the autoconf macro repository. We are also
50 | # grateful for the helpful feedback of numerous users.
51 | #
52 | # Updated for Autoconf 2.68 by Daniel Richard G.
53 | #
54 | # LICENSE
55 | #
56 | # Copyright (c) 2008 Steven G. Johnson
57 | # Copyright (c) 2011 Daniel Richard G.
58 | #
59 | # This program is free software: you can redistribute it and/or modify it
60 | # under the terms of the GNU General Public License as published by the
61 | # Free Software Foundation, either version 3 of the License, or (at your
62 | # option) any later version.
63 | #
64 | # This program is distributed in the hope that it will be useful, but
65 | # WITHOUT ANY WARRANTY; without even the implied warranty of
66 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
67 | # Public License for more details.
68 | #
69 | # You should have received a copy of the GNU General Public License along
70 | # with this program. If not, see .
71 | #
72 | # As a special exception, the respective Autoconf Macro's copyright owner
73 | # gives unlimited permission to copy, distribute and modify the configure
74 | # scripts that are the output of Autoconf when processing the Macro. You
75 | # need not follow the terms of the GNU General Public License when using
76 | # or distributing such scripts, even though portions of the text of the
77 | # Macro appear in them. The GNU General Public License (GPL) does govern
78 | # all other use of the material that constitutes the Autoconf Macro.
79 | #
80 | # This special exception to the GPL applies to versions of the Autoconf
81 | # Macro released by the Autoconf Archive. When you make and distribute a
82 | # modified version of the Autoconf Macro, you may extend this special
83 | # exception to the GPL to apply to your modified version as well.
84 |
85 | #serial 25
86 |
87 | AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
88 | AC_DEFUN([AX_PTHREAD], [
89 | AC_REQUIRE([AC_CANONICAL_HOST])
90 | AC_REQUIRE([AC_PROG_CC])
91 | AC_REQUIRE([AC_PROG_SED])
92 | AC_LANG_PUSH([C])
93 | ax_pthread_ok=no
94 |
95 | # We used to check for pthread.h first, but this fails if pthread.h
96 | # requires special compiler flags (e.g. on Tru64 or Sequent).
97 | # It gets checked for in the link test anyway.
98 |
99 | # First of all, check if the user has set any of the PTHREAD_LIBS,
100 | # etcetera environment variables, and if threads linking works using
101 | # them:
102 | if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
103 | ax_pthread_save_CC="$CC"
104 | ax_pthread_save_CFLAGS="$CFLAGS"
105 | ax_pthread_save_LIBS="$LIBS"
106 | AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
107 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
108 | LIBS="$PTHREAD_LIBS $LIBS"
109 | AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
110 | AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
111 | AC_MSG_RESULT([$ax_pthread_ok])
112 | if test "x$ax_pthread_ok" = "xno"; then
113 | PTHREAD_LIBS=""
114 | PTHREAD_CFLAGS=""
115 | fi
116 | CC="$ax_pthread_save_CC"
117 | CFLAGS="$ax_pthread_save_CFLAGS"
118 | LIBS="$ax_pthread_save_LIBS"
119 | fi
120 |
121 | # We must check for the threads library under a number of different
122 | # names; the ordering is very important because some systems
123 | # (e.g. DEC) have both -lpthread and -lpthreads, where one of the
124 | # libraries is broken (non-POSIX).
125 |
126 | # Create a list of thread flags to try. Items starting with a "-" are
127 | # C compiler flags, and other items are library names, except for "none"
128 | # which indicates that we try without any flags at all, and "pthread-config"
129 | # which is a program returning the flags for the Pth emulation library.
130 |
131 | ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
132 |
133 | # The ordering *is* (sometimes) important. Some notes on the
134 | # individual items follow:
135 |
136 | # pthreads: AIX (must check this before -lpthread)
137 | # none: in case threads are in libc; should be tried before -Kthread and
138 | # other compiler flags to prevent continual compiler warnings
139 | # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
140 | # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
141 | # (Note: HP C rejects this with "bad form for `-t' option")
142 | # -pthreads: Solaris/gcc (Note: HP C also rejects)
143 | # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
144 | # doesn't hurt to check since this sometimes defines pthreads and
145 | # -D_REENTRANT too), HP C (must be checked before -lpthread, which
146 | # is present but should not be used directly; and before -mthreads,
147 | # because the compiler interprets this as "-mt" + "-hreads")
148 | # -mthreads: Mingw32/gcc, Lynx/gcc
149 | # pthread: Linux, etcetera
150 | # --thread-safe: KAI C++
151 | # pthread-config: use pthread-config program (for GNU Pth library)
152 |
153 | case $host_os in
154 |
155 | freebsd*)
156 |
157 | # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
158 | # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
159 |
160 | ax_pthread_flags="-kthread lthread $ax_pthread_flags"
161 | ;;
162 |
163 | hpux*)
164 |
165 | # From the cc(1) man page: "[-mt] Sets various -D flags to enable
166 | # multi-threading and also sets -lpthread."
167 |
168 | ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
169 | ;;
170 |
171 | openedition*)
172 |
173 | # IBM z/OS requires a feature-test macro to be defined in order to
174 | # enable POSIX threads at all, so give the user a hint if this is
175 | # not set. (We don't define these ourselves, as they can affect
176 | # other portions of the system API in unpredictable ways.)
177 |
178 | AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
179 | [
180 | # if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
181 | AX_PTHREAD_ZOS_MISSING
182 | # endif
183 | ],
184 | [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
185 | ;;
186 |
187 | solaris*)
188 |
189 | # On Solaris (at least, for some versions), libc contains stubbed
190 | # (non-functional) versions of the pthreads routines, so link-based
191 | # tests will erroneously succeed. (N.B.: The stubs are missing
192 | # pthread_cleanup_push, or rather a function called by this macro,
193 | # so we could check for that, but who knows whether they'll stub
194 | # that too in a future libc.) So we'll check first for the
195 | # standard Solaris way of linking pthreads (-mt -lpthread).
196 |
197 | ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
198 | ;;
199 | esac
200 |
201 | # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
202 |
203 | AS_IF([test "x$GCC" = "xyes"],
204 | [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
205 |
206 | # The presence of a feature test macro requesting re-entrant function
207 | # definitions is, on some systems, a strong hint that pthreads support is
208 | # correctly enabled
209 |
210 | case $host_os in
211 | darwin* | hpux* | linux* | osf* | solaris*)
212 | ax_pthread_check_macro="_REENTRANT"
213 | ;;
214 |
215 | aix*)
216 | ax_pthread_check_macro="_THREAD_SAFE"
217 | ;;
218 |
219 | *)
220 | ax_pthread_check_macro="--"
221 | ;;
222 | esac
223 | AS_IF([test "x$ax_pthread_check_macro" = "x--"],
224 | [ax_pthread_check_cond=0],
225 | [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
226 |
227 | # Are we compiling with Clang?
228 |
229 | AC_CACHE_CHECK([whether $CC is Clang],
230 | [ax_cv_PTHREAD_CLANG],
231 | [ax_cv_PTHREAD_CLANG=no
232 | # Note that Autoconf sets GCC=yes for Clang as well as GCC
233 | if test "x$GCC" = "xyes"; then
234 | AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
235 | [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
236 | # if defined(__clang__) && defined(__llvm__)
237 | AX_PTHREAD_CC_IS_CLANG
238 | # endif
239 | ],
240 | [ax_cv_PTHREAD_CLANG=yes])
241 | fi
242 | ])
243 | ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
244 |
245 | ax_pthread_clang_warning=no
246 |
247 | # Clang needs special handling, because older versions handle the -pthread
248 | # option in a rather... idiosyncratic way
249 |
250 | if test "x$ax_pthread_clang" = "xyes"; then
251 |
252 | # Clang takes -pthread; it has never supported any other flag
253 |
254 | # (Note 1: This will need to be revisited if a system that Clang
255 | # supports has POSIX threads in a separate library. This tends not
256 | # to be the way of modern systems, but it's conceivable.)
257 |
258 | # (Note 2: On some systems, notably Darwin, -pthread is not needed
259 | # to get POSIX threads support; the API is always present and
260 | # active. We could reasonably leave PTHREAD_CFLAGS empty. But
261 | # -pthread does define _REENTRANT, and while the Darwin headers
262 | # ignore this macro, third-party headers might not.)
263 |
264 | PTHREAD_CFLAGS="-pthread"
265 | PTHREAD_LIBS=
266 |
267 | ax_pthread_ok=yes
268 |
269 | # However, older versions of Clang make a point of warning the user
270 | # that, in an invocation where only linking and no compilation is
271 | # taking place, the -pthread option has no effect ("argument unused
272 | # during compilation"). They expect -pthread to be passed in only
273 | # when source code is being compiled.
274 | #
275 | # Problem is, this is at odds with the way Automake and most other
276 | # C build frameworks function, which is that the same flags used in
277 | # compilation (CFLAGS) are also used in linking. Many systems
278 | # supported by AX_PTHREAD require exactly this for POSIX threads
279 | # support, and in fact it is often not straightforward to specify a
280 | # flag that is used only in the compilation phase and not in
281 | # linking. Such a scenario is extremely rare in practice.
282 | #
283 | # Even though use of the -pthread flag in linking would only print
284 | # a warning, this can be a nuisance for well-run software projects
285 | # that build with -Werror. So if the active version of Clang has
286 | # this misfeature, we search for an option to squash it.
287 |
288 | AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
289 | [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
290 | [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
291 | # Create an alternate version of $ac_link that compiles and
292 | # links in two steps (.c -> .o, .o -> exe) instead of one
293 | # (.c -> exe), because the warning occurs only in the second
294 | # step
295 | ax_pthread_save_ac_link="$ac_link"
296 | ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
297 | ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
298 | ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
299 | ax_pthread_save_CFLAGS="$CFLAGS"
300 | for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
301 | AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
302 | CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
303 | ac_link="$ax_pthread_save_ac_link"
304 | AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
305 | [ac_link="$ax_pthread_2step_ac_link"
306 | AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
307 | [break])
308 | ])
309 | done
310 | ac_link="$ax_pthread_save_ac_link"
311 | CFLAGS="$ax_pthread_save_CFLAGS"
312 | AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
313 | ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
314 | ])
315 |
316 | case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
317 | no | unknown) ;;
318 | *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
319 | esac
320 |
321 | fi # $ax_pthread_clang = yes
322 |
323 | if test "x$ax_pthread_ok" = "xno"; then
324 | for ax_pthread_try_flag in $ax_pthread_flags; do
325 |
326 | case $ax_pthread_try_flag in
327 | none)
328 | AC_MSG_CHECKING([whether pthreads work without any flags])
329 | ;;
330 |
331 | -mt,pthread)
332 | AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
333 | PTHREAD_CFLAGS="-mt"
334 | PTHREAD_LIBS="-lpthread"
335 | ;;
336 |
337 | -*)
338 | AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
339 | PTHREAD_CFLAGS="$ax_pthread_try_flag"
340 | ;;
341 |
342 | pthread-config)
343 | AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
344 | AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
345 | PTHREAD_CFLAGS="`pthread-config --cflags`"
346 | PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
347 | ;;
348 |
349 | *)
350 | AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
351 | PTHREAD_LIBS="-l$ax_pthread_try_flag"
352 | ;;
353 | esac
354 |
355 | ax_pthread_save_CFLAGS="$CFLAGS"
356 | ax_pthread_save_LIBS="$LIBS"
357 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
358 | LIBS="$PTHREAD_LIBS $LIBS"
359 |
360 | # Check for various functions. We must include pthread.h,
361 | # since some functions may be macros. (On the Sequent, we
362 | # need a special flag -Kthread to make this header compile.)
363 | # We check for pthread_join because it is in -lpthread on IRIX
364 | # while pthread_create is in libc. We check for pthread_attr_init
365 | # due to DEC craziness with -lpthreads. We check for
366 | # pthread_cleanup_push because it is one of the few pthread
367 | # functions on Solaris that doesn't have a non-functional libc stub.
368 | # We try pthread_create on general principles.
369 |
370 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include
371 | # if $ax_pthread_check_cond
372 | # error "$ax_pthread_check_macro must be defined"
373 | # endif
374 | static void routine(void *a) { a = 0; }
375 | static void *start_routine(void *a) { return a; }],
376 | [pthread_t th; pthread_attr_t attr;
377 | pthread_create(&th, 0, start_routine, 0);
378 | pthread_join(th, 0);
379 | pthread_attr_init(&attr);
380 | pthread_cleanup_push(routine, 0);
381 | pthread_cleanup_pop(0) /* ; */])],
382 | [ax_pthread_ok=yes],
383 | [])
384 |
385 | CFLAGS="$ax_pthread_save_CFLAGS"
386 | LIBS="$ax_pthread_save_LIBS"
387 |
388 | AC_MSG_RESULT([$ax_pthread_ok])
389 | AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
390 |
391 | PTHREAD_LIBS=""
392 | PTHREAD_CFLAGS=""
393 | done
394 | fi
395 |
396 | # Various other checks:
397 | if test "x$ax_pthread_ok" = "xyes"; then
398 | ax_pthread_save_CFLAGS="$CFLAGS"
399 | ax_pthread_save_LIBS="$LIBS"
400 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
401 | LIBS="$PTHREAD_LIBS $LIBS"
402 |
403 | # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
404 | AC_CACHE_CHECK([for joinable pthread attribute],
405 | [ax_cv_PTHREAD_JOINABLE_ATTR],
406 | [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
407 | for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
408 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ],
409 | [int attr = $ax_pthread_attr; return attr /* ; */])],
410 | [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
411 | [])
412 | done
413 | ])
414 | AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
415 | test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
416 | test "x$ax_pthread_joinable_attr_defined" != "xyes"],
417 | [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
418 | [$ax_cv_PTHREAD_JOINABLE_ATTR],
419 | [Define to necessary symbol if this constant
420 | uses a non-standard name on your system.])
421 | ax_pthread_joinable_attr_defined=yes
422 | ])
423 |
424 | AC_CACHE_CHECK([whether more special flags are required for pthreads],
425 | [ax_cv_PTHREAD_SPECIAL_FLAGS],
426 | [ax_cv_PTHREAD_SPECIAL_FLAGS=no
427 | case $host_os in
428 | solaris*)
429 | ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
430 | ;;
431 | esac
432 | ])
433 | AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
434 | test "x$ax_pthread_special_flags_added" != "xyes"],
435 | [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
436 | ax_pthread_special_flags_added=yes])
437 |
438 | AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
439 | [ax_cv_PTHREAD_PRIO_INHERIT],
440 | [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]],
441 | [[int i = PTHREAD_PRIO_INHERIT;
442 | return i;]])],
443 | [ax_cv_PTHREAD_PRIO_INHERIT=yes],
444 | [ax_cv_PTHREAD_PRIO_INHERIT=no])
445 | ])
446 | AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
447 | test "x$ax_pthread_prio_inherit_defined" != "xyes"],
448 | [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
449 | ax_pthread_prio_inherit_defined=yes
450 | ])
451 |
452 | CFLAGS="$ax_pthread_save_CFLAGS"
453 | LIBS="$ax_pthread_save_LIBS"
454 |
455 | # More AIX lossage: compile with *_r variant
456 | if test "x$GCC" != "xyes"; then
457 | case $host_os in
458 | aix*)
459 | AS_CASE(["x/$CC"],
460 | [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
461 | [#handle absolute path differently from PATH based program lookup
462 | AS_CASE(["x$CC"],
463 | [x/*],
464 | [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
465 | [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
466 | ;;
467 | esac
468 | fi
469 | fi
470 |
471 | test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
472 |
473 | AC_SUBST([PTHREAD_LIBS])
474 | AC_SUBST([PTHREAD_CFLAGS])
475 | AC_SUBST([PTHREAD_CC])
476 |
477 | # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
478 | if test "x$ax_pthread_ok" = "xyes"; then
479 | ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
480 | :
481 | else
482 | ax_pthread_ok=no
483 | $2
484 | fi
485 | AC_LANG_POP
486 | ])dnl AX_PTHREAD
487 |
--------------------------------------------------------------------------------
/src/dns_sender.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2021, OARC, Inc.
3 | * Copyright (c) 2019, DENIC eG
4 | * All rights reserved.
5 | *
6 | * This file is part of dnsmeter.
7 | *
8 | * dnsmeter is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * dnsmeter is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with dnsmeter. If not, see .
20 | */
21 |
22 | #include "config.h"
23 |
24 | #include "dns_sender.h"
25 | #include "exceptions.h"
26 | #include "dns_sender_thread.h"
27 |
28 | #include
29 | #include
30 |
31 | static const char* rcode_names[] = {
32 | "OK", "FORMAT", "SRVFAIL", "NAME", "NOTIMPL", "REFUSED",
33 | "YXDOMAIN", "YXRRSET", "NXRRSET", "NOTAUTH", "NOTZONE",
34 | "11", "12", "13", "14", "15",
35 | NULL
36 | };
37 |
38 | bool stopFlag = false;
39 |
40 | void sighandler(int sig)
41 | {
42 | stopFlag = true;
43 | printf("Stopping...\n");
44 | }
45 |
46 | void DNSSender::help()
47 | {
48 | ppl7::String name, underline;
49 | name.setf("dnsmeter %s", PACKAGE_VERSION);
50 | underline.repeat("=", name.size());
51 | name.printnl();
52 | underline.printnl();
53 | printf("\nUsage:\n"
54 | " -h shows this help\n"
55 | " -q HOST hostname or IP address of sender if you don't want to spoof\n"
56 | " (see -s)\n"
57 | " -s NET|pcap spoof sender address. Use random IP from the given network\n"
58 | " (example: 192.168.0.0/16). Only works when running as root!\n"
59 | " If payload is a pcap file, you can use \"-s pcap\" to use the\n"
60 | " source addresses and ports from the pcap file.\n"
61 | " -e ETH interface on which the packet receiver should listen\n"
62 | " (FreeBSD only)\n"
63 | " -z HOST:PORT hostname or IP address and port of the target nameserver\n"
64 | " -p FILE file with queries/payload or pcap file\n"
65 | " -l # runtime in seconds (default=10 seconds)\n"
66 | " -t # timeout in seconds (default=2 seconds)\n"
67 | " -n # number of worker threads (default=1)\n"
68 | " -r # queryrate (Default=as much as possible)\n"
69 | " can be a single value, a comma separated list (rate,rate,...)\n"
70 | " or a range and a step value (start - end, step)\n"
71 | " -d # amount of queries in percent on which the DNSSEC-flags are set\n"
72 | " (default=0)\n"
73 | " -c FILE CSV-file for results\n"
74 | " --ignore answers are ignored and therefor not counted. In this mode\n"
75 | " the tool only generates traffic."
76 | "\n");
77 | }
78 |
79 | DNSSender::Results::Results()
80 | {
81 | queryrate = 0;
82 | counter_send = 0;
83 | counter_received = 0;
84 | bytes_send = 0;
85 | bytes_received = 0;
86 | counter_errors = 0;
87 | packages_lost = 0;
88 | counter_0bytes = 0;
89 | for (int i = 0; i < 255; i++)
90 | counter_errorcodes[i] = 0;
91 | rtt_avg = 0.0f;
92 | rtt_total = 0.0f;
93 | rtt_min = 0.0f;
94 | rtt_max = 0.0f;
95 | for (int i = 0; i < 16; i++)
96 | rcodes[i] = 0;
97 | truncated = 0;
98 | }
99 |
100 | void DNSSender::Results::clear()
101 | {
102 | queryrate = 0;
103 | counter_send = 0;
104 | counter_received = 0;
105 | bytes_send = 0;
106 | bytes_received = 0;
107 | counter_errors = 0;
108 | packages_lost = 0;
109 | counter_0bytes = 0;
110 | for (int i = 0; i < 255; i++)
111 | counter_errorcodes[i] = 0;
112 | rtt_avg = 0.0f;
113 | rtt_total = 0.0f;
114 | rtt_min = 0.0f;
115 | rtt_max = 0.0f;
116 | for (int i = 0; i < 16; i++)
117 | rcodes[i] = 0;
118 | truncated = 0;
119 | }
120 |
121 | DNSSender::Results operator-(const DNSSender::Results& second, const DNSSender::Results& first)
122 | {
123 | DNSSender::Results r;
124 | r.queryrate = second.queryrate - first.queryrate;
125 | r.counter_send = second.counter_send - first.counter_send;
126 | r.counter_received = second.counter_received - first.counter_received;
127 | r.bytes_send = second.bytes_send - first.bytes_send;
128 | r.bytes_received = second.bytes_received - first.bytes_received;
129 | r.counter_errors = second.counter_errors - first.counter_errors;
130 | r.packages_lost = second.packages_lost - first.packages_lost;
131 | r.counter_0bytes = second.counter_0bytes - first.counter_0bytes;
132 | for (int i = 0; i < 255; i++)
133 | r.counter_errorcodes[i] = second.counter_errorcodes[i] - first.counter_errorcodes[i];
134 | r.rtt_total = second.rtt_total - first.rtt_total;
135 | if (r.counter_received)
136 | r.rtt_avg = r.rtt_total / r.counter_received; //NOSONAR
137 | else
138 | r.rtt_avg = 0.0;
139 | r.rtt_min = second.rtt_min - first.rtt_min;
140 | r.rtt_max = second.rtt_max - first.rtt_max;
141 |
142 | for (int i = 0; i < 16; i++)
143 | r.rcodes[i] = second.rcodes[i] - first.rcodes[i];
144 | r.truncated = second.truncated - first.truncated;
145 | return r;
146 | }
147 |
148 | DNSSender::DNSSender()
149 | {
150 | ppl7::InitSockets();
151 | Runtime = 10;
152 | Timeout = 2;
153 | ThreadCount = 1;
154 | Timeslices = 1.0f;
155 | ignoreResponses = false;
156 | DnssecRate = 0;
157 | TargetPort = 53;
158 | spoofingEnabled = false;
159 | Receiver = NULL;
160 | spoofFromPcap = false;
161 | }
162 |
163 | DNSSender::~DNSSender()
164 | {
165 | if (Receiver)
166 | delete Receiver;
167 | }
168 |
169 | ppl7::Array DNSSender::getQueryRates(const ppl7::String& QueryRates)
170 | {
171 | ppl7::Array rates;
172 | if (QueryRates.isEmpty()) {
173 | rates.add("0");
174 | } else {
175 | ppl7::Array matches;
176 | if (QueryRates.pregMatch("/^([0-9]+)-([0-9]+),([0-9]+)$", matches)) {
177 | for (ppluint64 i = matches[1].toUnsignedInt64(); i <= matches[2].toUnsignedInt64(); i += matches[3].toUnsignedInt64()) {
178 | rates.addf("%llu", i);
179 | }
180 | } else {
181 | rates.explode(QueryRates, ",");
182 | }
183 | }
184 | return rates;
185 | }
186 |
187 | void DNSSender::getTarget(int argc, char** argv)
188 | {
189 | if (!ppl7::HaveArgv(argc, argv, "-z")) {
190 | throw MissingCommandlineParameter("target IP/hostname or port missing (-z IP:PORT)");
191 | }
192 | ppl7::String Tmp = ppl7::GetArgv(argc, argv, "-z");
193 | ppl7::Array Tok(Tmp, ":");
194 | if (Tok.size() != 2) {
195 | if (Tok.size() != 1)
196 | throw InvalidCommandlineParameter("-z IP:PORT");
197 | TargetPort = 53;
198 | } else {
199 | TargetPort = Tok[1].toInt();
200 | }
201 | if (TargetPort < 1 || TargetPort > 65535)
202 | throw InvalidCommandlineParameter("-z IP:PORT, Invalid Port");
203 | std::list Result;
204 | size_t num = ppl7::GetHostByName(Tok[0], Result, ppl7::af_inet);
205 | if (!num)
206 | throw InvalidCommandlineParameter("-z IP:PORT, Invalid IP or could not resolve Hostname");
207 | TargetIP = Result.front();
208 | //printf ("num=%d, %s\n",num, (const char*)TargetIP.toString());
209 | }
210 |
211 | void DNSSender::getSource(int argc, char** argv)
212 | {
213 | if (ppl7::HaveArgv(argc, argv, "-s")) {
214 | ppl7::String Tmp = ppl7::GetArgv(argc, argv, "-s").toLowerCase();
215 | if (Tmp == "pcap") {
216 | spoofFromPcap = true;
217 | } else {
218 | SourceNet.set(Tmp);
219 | if (SourceNet.family() != ppl7::IPAddress::IPv4)
220 | throw UnsupportedIPFamily("only IPv4 works");
221 | }
222 | spoofingEnabled = true;
223 | } else {
224 | ppl7::String Tmp = ppl7::GetArgv(argc, argv, "-q");
225 | std::list Result;
226 | size_t num = ppl7::GetHostByName(Tmp, Result, ppl7::af_inet);
227 | if (!num)
228 | throw InvalidCommandlineParameter("-q HOST, Invalid IP or could not resolve Hostname");
229 | SourceIP = Result.front();
230 | if (SourceIP.family() != ppl7::IPAddress::IPv4)
231 | throw UnsupportedIPFamily("only IPv4 works");
232 | spoofingEnabled = false;
233 | }
234 | }
235 |
236 | int DNSSender::getParameter(int argc, char** argv)
237 | {
238 | if (ppl7::HaveArgv(argc, argv, "-q") && ppl7::HaveArgv(argc, argv, "-s")) {
239 | printf("ERROR: could not use parameters -q and -s together\n\n");
240 | help();
241 | return 1;
242 | }
243 | if ((!ppl7::HaveArgv(argc, argv, "-q")) && (!ppl7::HaveArgv(argc, argv, "-s"))) {
244 | printf("ERROR: source IP/hostname or network for source address spoofing missing (-q IP | -s NETWORK)\n\n");
245 | help();
246 | return 1;
247 | }
248 | ignoreResponses = ppl7::HaveArgv(argc, argv, "--ignore");
249 |
250 | if (ppl7::HaveArgv(argc, argv, "-e")) {
251 | InterfaceName = ppl7::GetArgv(argc, argv, "-e");
252 | }
253 |
254 | try {
255 | getTarget(argc, argv);
256 | getSource(argc, argv);
257 | } catch (const ppl7::Exception& e) {
258 | printf("ERROR: missing or invalid parameter\n");
259 | e.print();
260 | printf("\n");
261 | help();
262 | return 1;
263 | }
264 |
265 | Runtime = ppl7::GetArgv(argc, argv, "-l").toInt();
266 | Timeout = ppl7::GetArgv(argc, argv, "-t").toInt();
267 | ThreadCount = ppl7::GetArgv(argc, argv, "-n").toInt();
268 | ppl7::String QueryRates = ppl7::GetArgv(argc, argv, "-r");
269 | CSVFileName = ppl7::GetArgv(argc, argv, "-c");
270 | QueryFilename = ppl7::GetArgv(argc, argv, "-p");
271 | if (ppl7::HaveArgv(argc, argv, "-d")) {
272 | DnssecRate = ppl7::GetArgv(argc, argv, "-d").toInt();
273 | if (DnssecRate < 0 || DnssecRate > 100) {
274 | printf("ERROR: DNSSEC-Rate must be an integer between 0 and 100 (-d #)\n\n");
275 | help();
276 | return 1;
277 | }
278 | }
279 | if (!ThreadCount)
280 | ThreadCount = 1;
281 | if (!Runtime)
282 | Runtime = 10;
283 | if (!Timeout)
284 | Timeout = 2;
285 | if (QueryFilename.isEmpty()) {
286 | printf("ERROR: Payload-File is missing (-p FILENAME)\n\n");
287 | help();
288 | return 1;
289 | }
290 | rates = getQueryRates(QueryRates);
291 | return 0;
292 | }
293 |
294 | int DNSSender::openFiles()
295 | {
296 | if (CSVFileName.notEmpty()) {
297 | try {
298 | openCSVFile(CSVFileName);
299 | } catch (const ppl7::Exception& e) {
300 | printf("ERROR: could not open CSV-file for writing\n");
301 | e.print();
302 | return 1;
303 | }
304 | }
305 | try {
306 | payload.openQueryFile(QueryFilename);
307 | } catch (const ppl7::Exception& e) {
308 | printf("ERROR: could not open payload file or it does not contain any queries\n");
309 | e.print();
310 | return 1;
311 | }
312 | return 0;
313 | }
314 |
315 | int DNSSender::main(int argc, char** argv)
316 | {
317 | if (ppl7::HaveArgv(argc, argv, "-h") || ppl7::HaveArgv(argc, argv, "--help") || argc < 2) {
318 | help();
319 | return 0;
320 | }
321 | if (getParameter(argc, argv) != 0)
322 | return 1;
323 | if (openFiles() != 0)
324 | return 1;
325 |
326 | signal(SIGINT, sighandler);
327 | signal(SIGKILL, sighandler);
328 |
329 | DNSSender::Results results;
330 | try {
331 | if (!ignoreResponses) {
332 | Receiver = new DNSReceiverThread();
333 | Receiver->setSource(TargetIP, TargetPort);
334 | try {
335 | Receiver->setInterface(InterfaceName);
336 | } catch (const ppl7::Exception& e) {
337 | printf("ERROR: could not bind on device [%s]\n", (const char*)InterfaceName);
338 | e.print();
339 | printf("\n");
340 | help();
341 | return 1;
342 | }
343 | }
344 | prepareThreads();
345 | for (size_t i = 0; i < rates.size(); i++) {
346 | results.queryrate = rates[i].toInt();
347 | run(rates[i].toInt());
348 | getResults(results);
349 | presentResults(results);
350 | saveResultsToCsv(results);
351 | }
352 | threadpool.destroyAllThreads();
353 | } catch (const ppl7::OperationInterruptedException&) {
354 | getResults(results);
355 | presentResults(results);
356 | saveResultsToCsv(results);
357 | } catch (const ppl7::Exception& e) {
358 | e.print();
359 | return 1;
360 | }
361 | return 0;
362 | }
363 |
364 | void DNSSender::prepareThreads()
365 | {
366 | for (int i = 0; i < ThreadCount; i++) {
367 | DNSSenderThread* thread = new DNSSenderThread();
368 | thread->setDestination(TargetIP, TargetPort);
369 | thread->setRuntime(Runtime);
370 | thread->setTimeout(Timeout);
371 | thread->setTimeslice(Timeslices);
372 | thread->setDNSSECRate(DnssecRate);
373 | thread->setVerbose(false);
374 | thread->setPayload(payload);
375 | if (spoofingEnabled) {
376 | if (spoofFromPcap)
377 | thread->setSourcePcap();
378 | else
379 | thread->setSourceNet(SourceNet);
380 | } else {
381 | thread->setSourceIP(SourceIP);
382 | }
383 | threadpool.addThread(thread);
384 | }
385 | }
386 |
387 | void DNSSender::openCSVFile(const ppl7::String& Filename)
388 | {
389 | CSVFile.open(Filename, ppl7::File::APPEND);
390 | if (CSVFile.size() == 0) {
391 | CSVFile.putsf("#QPS Send; QPS Received; QPS Errors; Lostrate; "
392 | "rtt_avg; rtt_min; rtt_max;"
393 | "\n");
394 | CSVFile.flush();
395 | }
396 | }
397 |
398 | void DNSSender::showCurrentStats(ppl7::ppl_time_t start_time)
399 | {
400 | DNSSender::Results result, diff;
401 | ppl7::ppl_time_t runtime = ppl7::GetTime() - start_time;
402 | getResults(result);
403 | diff = result - vis_prev_results;
404 | vis_prev_results = result;
405 |
406 | int h = (int)(runtime / 3600);
407 | runtime -= h * 3600;
408 | int m = (int)(runtime / 60);
409 | int s = runtime - (m * 60);
410 |
411 | printf("%02d:%02d:%02d Queries send: %7llu, rcv: %7llu, ", h, m, s,
412 | diff.counter_send, diff.counter_received);
413 | printf("Data send: %6llu KB, rcv: %6llu KB", diff.bytes_send / 1024, diff.bytes_received / 1024);
414 | printf("\n");
415 | }
416 |
417 | void DNSSender::calcTimeslice(int queryrate)
418 | {
419 | Timeslices = (1000.0f / queryrate) * ThreadCount; //NOSONAR
420 | //if (Zeitscheibe<1.0f) Zeitscheibe=1.0f;
421 | if (Timeslices < 0.1f)
422 | Timeslices = 0.1f;
423 | }
424 |
425 | void DNSSender::run(int queryrate)
426 | {
427 | printf("###############################################################################\n");
428 | if (queryrate) {
429 | calcTimeslice(queryrate);
430 | printf("# Start Session with Threads: %d, Queryrate: %d, Timeslot: %0.6f ms\n",
431 | ThreadCount, queryrate, Timeslices);
432 | } else {
433 | printf("# Start Session with Threads: %d, Queryrate: unlimited\n",
434 | ThreadCount);
435 | }
436 |
437 | ppl7::ThreadPool::iterator it;
438 | for (it = threadpool.begin(); it != threadpool.end(); ++it) {
439 | ((DNSSenderThread*)(*it))->setQueryRate(queryrate / ThreadCount);
440 | ((DNSSenderThread*)(*it))->setTimeslice(Timeslices);
441 | }
442 | vis_prev_results.clear();
443 | sampleSensorData(sys1);
444 | if (Receiver)
445 | Receiver->threadStart();
446 | threadpool.startThreads();
447 | ppl7::ppl_time_t start = ppl7::GetTime();
448 | ppl7::ppl_time_t report = start + 1;
449 | ppl7::MSleep(500);
450 | while (threadpool.running() == true && stopFlag == false) {
451 | ppl7::MSleep(100);
452 | ppl7::ppl_time_t now = ppl7::GetTime();
453 | if (now >= report) {
454 | report = now + 1;
455 | showCurrentStats(start);
456 | }
457 | }
458 | if (Receiver)
459 | Receiver->threadStop();
460 | sampleSensorData(sys2);
461 | if (stopFlag == true) {
462 | threadpool.stopThreads();
463 | throw ppl7::OperationInterruptedException("test aborted");
464 | }
465 | }
466 |
467 | void DNSSender::getResults(DNSSender::Results& result)
468 | {
469 | ppl7::ThreadPool::iterator it;
470 | result.clear();
471 |
472 | for (it = threadpool.begin(); it != threadpool.end(); ++it) {
473 | result.counter_send += ((DNSSenderThread*)(*it))->getPacketsSend();
474 | result.bytes_send += ((DNSSenderThread*)(*it))->getBytesSend();
475 | result.counter_errors += ((DNSSenderThread*)(*it))->getErrors();
476 | result.counter_0bytes += ((DNSSenderThread*)(*it))->getCounter0Bytes();
477 | for (int i = 0; i < 255; i++)
478 | result.counter_errorcodes[i] += ((DNSSenderThread*)(*it))->getCounterErrorCode(i);
479 | }
480 | if (Receiver) {
481 | const RawSocketReceiver::Counter& counter = Receiver->getCounter();
482 | result.counter_received = counter.num_pkgs;
483 | result.bytes_received = counter.bytes_rcv;
484 | result.rtt_total = counter.rtt_total;
485 | if (counter.num_pkgs)
486 | result.rtt_avg = counter.rtt_total / counter.num_pkgs; //NOSONAR
487 | else
488 | result.rtt_avg = 0.0;
489 | result.rtt_min = counter.rtt_min;
490 | result.rtt_max = counter.rtt_max;
491 | for (int i = 0; i < 16; i++)
492 | result.rcodes[i] = counter.rcodes[i];
493 | result.truncated = counter.truncated;
494 | }
495 |
496 | result.packages_lost = result.counter_send - result.counter_received;
497 | if (result.counter_received > result.counter_send)
498 | result.packages_lost = 0;
499 | }
500 |
501 | void DNSSender::saveResultsToCsv(const DNSSender::Results& result)
502 | {
503 |
504 | if (CSVFile.isOpen()) {
505 | CSVFile.putsf("%llu;%llu;%llu;%0.3f;%0.4f;%0.4f;%0.4f;\n",
506 | (ppluint64)((double)result.counter_send / (double)Runtime),
507 | (ppluint64)((double)result.counter_received / (double)Runtime),
508 | (ppluint64)((double)result.counter_errors / (double)Runtime),
509 | (double)result.packages_lost * 100.0 / (double)result.counter_send,
510 | result.rtt_avg * 1000.0,
511 | result.rtt_min * 1000.0,
512 | result.rtt_max * 1000.0);
513 | CSVFile.flush();
514 | }
515 | }
516 |
517 | void DNSSender::presentResults(const DNSSender::Results& result)
518 | {
519 | printf("===============================================================================\n");
520 | const SystemStat::Interface& net1 = sys1.interfaces[InterfaceName];
521 | const SystemStat::Interface& net2 = sys2.interfaces[InterfaceName];
522 | SystemStat::Network transmit = SystemStat::Network::getDelta(net1.transmit, net2.transmit);
523 | SystemStat::Network received = SystemStat::Network::getDelta(net1.receive, net2.receive);
524 | printf("network if %s Pkt send: %lu, rcv: %lu, Data send: %lu KB, rcv: %lu KB\n",
525 | (const char*)InterfaceName,
526 | transmit.packets, received.packets, transmit.bytes / 1024, received.bytes / 1024);
527 |
528 | ppluint64 qps_send = (ppluint64)((double)result.counter_send / (double)Runtime);
529 | ppluint64 bps_send = (ppluint64)((double)result.bytes_send / (double)Runtime);
530 | ppluint64 qps_received = (ppluint64)((double)result.counter_received / (double)Runtime);
531 | ppluint64 bps_received = (ppluint64)((double)result.bytes_received / (double)Runtime);
532 |
533 | printf("DNS Queries send: %10llu, Qps: %7llu, Data send: %7llu KB = %6llu MBit\n",
534 | result.counter_send, qps_send, result.bytes_send / 1024, bps_send / (1024 * 1024));
535 |
536 | printf("DNS Queries rcv: %10llu, Qps: %7llu, Data rcv: %7llu KB = %6llu MBit\n",
537 | result.counter_received, qps_received, result.bytes_received / 1024, bps_received / (1024 * 1024));
538 |
539 | printf("DNS Queries lost: %10llu = %0.3f %%\n", result.packages_lost,
540 | (double)result.packages_lost * 100.0 / (double)result.counter_send);
541 |
542 | printf("DNS rtt average: %0.4f ms, "
543 | "min: %0.4f ms, "
544 | "max: %0.4f ms\n",
545 | result.rtt_avg * 1000.0,
546 | result.rtt_min * 1000.0,
547 | result.rtt_max * 1000.0);
548 | printf("DNS truncated: %llu\nDNS RCODES: ", result.truncated);
549 | for (int i = 0; i < 15; i++) {
550 | if (result.rcodes[i]) {
551 | printf("%s: %llu, ", rcode_names[i], result.rcodes[i]);
552 | }
553 | }
554 | printf("\n");
555 |
556 | if (result.counter_errors) {
557 | printf("Errors: %10llu, Qps: %10llu\n", result.counter_errors,
558 | (ppluint64)((double)result.counter_errors / (double)Runtime));
559 | }
560 | if (result.counter_0bytes) {
561 | printf("Errors 0Byte: %10llu, Qps: %10llu\n", result.counter_0bytes,
562 | (ppluint64)((double)result.counter_0bytes / (double)Runtime));
563 | }
564 | for (int i = 0; i < 255; i++) {
565 | if (result.counter_errorcodes[i] > 0) {
566 | printf("Errors %3d: %10llu, Qps: %10llu [%s]\n", i, result.counter_errorcodes[i],
567 | (ppluint64)((double)result.counter_errorcodes[i] / (double)Runtime),
568 | strerror(i));
569 | }
570 | }
571 | }
572 |
--------------------------------------------------------------------------------