Adding upstream version 2.0.0+debian.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
65eb8bc08a
commit
1cf0d30d41
191 changed files with 48816 additions and 0 deletions
1
plugins/rssm/.gitignore
vendored
Normal file
1
plugins/rssm/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
hashtbl.c
|
42
plugins/rssm/Makefile.am
Normal file
42
plugins/rssm/Makefile.am
Normal file
|
@ -0,0 +1,42 @@
|
|||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
CLEANFILES = $(srcdir)/hashtbl.c \
|
||||
hashtbl.c *.gcda *.gcno *.gcov
|
||||
|
||||
AM_CFLAGS = -I$(srcdir) \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/isc \
|
||||
$(SECCOMPFLAGS) \
|
||||
$(libldns_CFLAGS)
|
||||
|
||||
pkglib_LTLIBRARIES = rssm.la
|
||||
rssm_la_SOURCES = rssm.c
|
||||
nodist_rssm_la_SOURCES = hashtbl.c
|
||||
BUILT_SOURCES = hashtbl.c
|
||||
rssm_la_LDFLAGS = -module -avoid-version $(libldns_LIBS)
|
||||
TESTS = test1.sh test2.sh test3.sh test4.sh test5.sh
|
||||
EXTRA_DIST = $(TESTS) test1.gold test2.gold dnscap-rssm-rssac002.1.in \
|
||||
test3.gold test5.gold
|
||||
dist_bin_SCRIPTS = dnscap-rssm-rssac002
|
||||
man1_MANS = dnscap-rssm-rssac002.1
|
||||
CLEANFILES += test1.20161020.152301.075993 test2.out $(man1_MANS) \
|
||||
test3.20181127.155200.414188 test4.*20161020.152301.075993 \
|
||||
test5.20180110.112241.543825
|
||||
|
||||
if ENABLE_GCOV
|
||||
gcov-local:
|
||||
for src in $(rssm_la_SOURCES) $(nodist_rssm_la_SOURCES); do \
|
||||
gcov -o .libs -l -r -s "$(srcdir)" "$$src"; \
|
||||
done
|
||||
endif
|
||||
|
||||
hashtbl.c: $(top_srcdir)/src/hashtbl.c
|
||||
cp $(top_srcdir)/src/hashtbl.c ./
|
||||
|
||||
$(srcdir)/hashtbl.c: $(top_srcdir)/src/hashtbl.c
|
||||
cp $(top_srcdir)/src/hashtbl.c $(srcdir)/
|
||||
|
||||
dnscap-rssm-rssac002.1: dnscap-rssm-rssac002.1.in Makefile
|
||||
sed -e 's,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g' \
|
||||
-e 's,[@]PACKAGE_URL[@],$(PACKAGE_URL),g' \
|
||||
-e 's,[@]PACKAGE_BUGREPORT[@],$(PACKAGE_BUGREPORT),g' \
|
||||
< $(srcdir)/dnscap-rssm-rssac002.1.in > dnscap-rssm-rssac002.1
|
41
plugins/rssm/README.md
Normal file
41
plugins/rssm/README.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Root Server Scaling Measurement (RSSM) plugin
|
||||
|
||||
This plugin collects data as described by the [RSSAC002v3 specification](https://www.icann.org/en/system/files/files/rssac-002-measurements-root-06jun16-en.pdf)
|
||||
which has been created by [ICANN Root Server System Advisory Committee](https://www.icann.org/groups/rssac) (RSSAC).
|
||||
|
||||
## Additions
|
||||
|
||||
As the RSSAC002v3 specification states that measurements should be saved per
|
||||
24 hours interval, this plugin produces additional metrics that can be used
|
||||
to compile the 24 hours measurements allowing for variable time between
|
||||
output generation.
|
||||
|
||||
Metric `dnscap-rssm-sources` has a hash entry called `sources` which lists
|
||||
IP addresses and the number of times they appeared.
|
||||
|
||||
Metric `dnscap-rssm-aggregated-sources` has a hash entry called `aggregated-sources`
|
||||
which lists the aggregated IPv6 addresses by a /64 net and the number of times
|
||||
it has appeared.
|
||||
|
||||
## Merge Tool
|
||||
|
||||
The Perl script `dnscap-rssm-rssac002` is included and installed with `dnscap`
|
||||
and can be used to multiple combine RSSM plugin RSSAC002v3 YAML output files
|
||||
into one file.
|
||||
|
||||
The script will merge and remove metric specific to this plugin and replace
|
||||
others to fill in correct values for the new time period. The earliest
|
||||
`start-period` found will be used for all metrics.
|
||||
|
||||
**NOTE** no parsing of `start-period` is performed, it is up to the operator
|
||||
to only give input files related to the same 24 hour period.
|
||||
|
||||
Options:
|
||||
- `--no-recompile`: Disabled the combining of metrics and the removal of
|
||||
metrics specific to this plugin
|
||||
- `--keep-dnscap-rssm`: Do the combining but keep the metrics specific to
|
||||
this plugin
|
||||
- `--sort`: Output will always start with `version:`, `service:`,
|
||||
`start-period:` and `metric:`, rest of the values are not ordered by label.
|
||||
This option enabled sorting of them, which is not required by the
|
||||
specification but may help in debugging and testing cases.
|
209
plugins/rssm/dnscap-rssm-rssac002
Executable file
209
plugins/rssm/dnscap-rssm-rssac002
Executable file
|
@ -0,0 +1,209 @@
|
|||
#!/usr/bin/env perl
|
||||
#
|
||||
# Copyright (c) 2018-2021, OARC, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use YAML;
|
||||
|
||||
unless (scalar @ARGV > 1) {
|
||||
print "usage: dnscap-rssm-rssac002 [--no-recompile|--keep-dnscap-rssm|--sort] <YAML files to merge...>\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
my %service = ();
|
||||
my $earliest_start_period;
|
||||
my $recompile = 1;
|
||||
my $keep_dnscap_rssm = 0;
|
||||
my $sort = 0;
|
||||
|
||||
foreach my $file (@ARGV) {
|
||||
if ($file eq '--no-recompile') {
|
||||
$recompile = 0;
|
||||
next;
|
||||
} elsif ($file eq '--keep-dnscap-rssm') {
|
||||
$keep_dnscap_rssm = 1;
|
||||
next;
|
||||
} elsif ($file eq '--sort') {
|
||||
$sort = 1;
|
||||
next;
|
||||
}
|
||||
foreach my $doc (YAML::LoadFile($file)) {
|
||||
my $version = delete $doc->{version};
|
||||
my $service = delete $doc->{service};
|
||||
my $start_period = delete $doc->{'start-period'};
|
||||
my $metric = delete $doc->{metric};
|
||||
unless ($version) {
|
||||
die "$file: not valid RSSAC002 YAML, missing version";
|
||||
}
|
||||
unless ($service) {
|
||||
die "$file: not valid RSSAC002 YAML, missing service";
|
||||
}
|
||||
unless ($start_period) {
|
||||
die "$file: not valid RSSAC002 YAML, missing start-period";
|
||||
}
|
||||
unless ($metric) {
|
||||
die "$file: not valid RSSAC002 YAML, missing metric";
|
||||
}
|
||||
unless ($version eq 'rssac002v3') {
|
||||
die "$file: unsupported RSSAC002 version $version";
|
||||
}
|
||||
|
||||
push(@{$service{$service}->{$metric}}, $doc);
|
||||
|
||||
if (!$earliest_start_period or $start_period lt $earliest_start_period) {
|
||||
$earliest_start_period = $start_period;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $service (keys %service) {
|
||||
foreach my $metric (keys %{$service{$service}}) {
|
||||
my %doc = ();
|
||||
foreach (@{$service{$service}->{$metric}}) {
|
||||
eval {
|
||||
merge(\%doc, $_);
|
||||
};
|
||||
if ($@) {
|
||||
die "service $service metric $metric: $@";
|
||||
}
|
||||
}
|
||||
$service{$service}->{$metric} = \%doc;
|
||||
}
|
||||
}
|
||||
|
||||
if ($recompile) {
|
||||
foreach my $service (keys %service) {
|
||||
my ($ipv4, $ipv6, $aggregated) = (0, 0, 0);
|
||||
my $metric;
|
||||
|
||||
if ($keep_dnscap_rssm) {
|
||||
$metric = $service{$service}->{'dnscap-rssm-sources'};
|
||||
} else {
|
||||
$metric = delete $service{$service}->{'dnscap-rssm-sources'};
|
||||
}
|
||||
if ($metric) {
|
||||
if (ref($metric->{sources}) eq 'HASH') {
|
||||
foreach my $ip (keys %{$metric->{sources}}) {
|
||||
if ($ip =~ /:/o) {
|
||||
$ipv6++;
|
||||
} else {
|
||||
$ipv4++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($keep_dnscap_rssm) {
|
||||
$metric = $service{$service}->{'dnscap-rssm-aggregated-sources'};
|
||||
} else {
|
||||
$metric = delete $service{$service}->{'dnscap-rssm-aggregated-sources'};
|
||||
}
|
||||
if ($metric) {
|
||||
if (ref($metric->{'aggregated-sources'}) eq 'HASH') {
|
||||
my @keys = keys %{$metric->{'aggregated-sources'}};
|
||||
$aggregated += scalar @keys;
|
||||
}
|
||||
}
|
||||
|
||||
$service{$service}->{'unique-sources'} = {
|
||||
'num-sources-ipv4' => $ipv4,
|
||||
'num-sources-ipv6' => $ipv6,
|
||||
'num-sources-ipv6-aggregate' => $aggregated,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if ($sort) {
|
||||
my $first = 1;
|
||||
$YAML::SortKeys = 1;
|
||||
foreach my $service (sort keys %service) {
|
||||
foreach my $metric (sort keys %{$service{$service}}) {
|
||||
if ($first) {
|
||||
$first = 0;
|
||||
} else {
|
||||
print "\n";
|
||||
}
|
||||
print YAML::Dump({
|
||||
version => "rssac002v3",
|
||||
service => $service,
|
||||
'start-period' => $earliest_start_period,
|
||||
metric => $metric,
|
||||
%{ $service{$service}->{$metric} },
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
my $first = 1;
|
||||
$YAML::SortKeys = 0;
|
||||
foreach my $service (keys %service) {
|
||||
foreach my $metric (keys %{$service{$service}}) {
|
||||
if ($first) {
|
||||
$first = 0;
|
||||
} else {
|
||||
print "\n";
|
||||
}
|
||||
print YAML::Dump({
|
||||
version => "rssac002v3",
|
||||
service => $service,
|
||||
'start-period' => $earliest_start_period,
|
||||
metric => $metric,
|
||||
%{ $service{$service}->{$metric} },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub merge {
|
||||
my ( $doc, $measurements ) = @_;
|
||||
|
||||
foreach my $key (keys %$measurements) {
|
||||
if (ref($doc->{$key}) eq 'HASH') {
|
||||
unless (ref($measurements->{$key}) eq 'HASH') {
|
||||
die "invalid measurement types for key $key: not a hash";
|
||||
}
|
||||
eval {
|
||||
merge($doc->{$key}, $measurements->{$key});
|
||||
};
|
||||
die $@ if ($@);
|
||||
next;
|
||||
}
|
||||
if (defined($doc->{$key})) {
|
||||
if (defined($measurements->{$key}) and $measurements->{$key} ne '') {
|
||||
$doc->{$key} += $measurements->{$key};
|
||||
}
|
||||
} else {
|
||||
$doc->{$key} = $measurements->{$key};
|
||||
}
|
||||
}
|
||||
}
|
98
plugins/rssm/dnscap-rssm-rssac002.1.in
Normal file
98
plugins/rssm/dnscap-rssm-rssac002.1.in
Normal file
|
@ -0,0 +1,98 @@
|
|||
.\" Copyright (c) 2017-2021, OARC, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\"
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\"
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in
|
||||
.\" the documentation and/or other materials provided with the
|
||||
.\" distribution.
|
||||
.\"
|
||||
.\" 3. Neither the name of the copyright holder nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
.\" COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
.\" CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.TH dnscap-rssm-rssac002 1 "dnscap-v@PACKAGE_VERSION@" "dnscap RSSAC002v3 Tool"
|
||||
.SH NAME
|
||||
dnscap-rssm-rssac002 \- Combine RSSAC002v3 YAML files
|
||||
.SH SYNOPSIS
|
||||
.B dnscap-rssm-rssac002
|
||||
[
|
||||
.B \--no-recompile
|
||||
.B \--keep-dnscap-rssm
|
||||
.B \--sort
|
||||
]
|
||||
.I files...
|
||||
.SH DESCRIPTION
|
||||
This Perl script will merge and remove metric specific to this plugin and
|
||||
replace others to fill in correct values for the new time period.
|
||||
The earliest
|
||||
.I start-period
|
||||
found will be used for all metrics.
|
||||
.LP
|
||||
.B NOTE
|
||||
no parsing of
|
||||
.I start-period
|
||||
is performed, it is up to the operator to only give input files related
|
||||
to the same 24 hour period.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \--no-recompile
|
||||
Disabled the combining of metrics and the removal of metrics specific to
|
||||
this plugin.
|
||||
.TP
|
||||
.B \--keep-dnscap-rssm
|
||||
Do the combining but keep the metrics specific to this plugin.
|
||||
.TP
|
||||
.B \--sort
|
||||
Output will always start with
|
||||
.IR version: ,
|
||||
.IR service: ,
|
||||
.I start-period:
|
||||
and
|
||||
.IR metric: ,
|
||||
rest of the values are not ordered by label.
|
||||
This option enabled sorting of them, which is not required by the
|
||||
specification but may help in debugging and testing cases.
|
||||
.SH SEE ALSO
|
||||
.BR dnscap (1)
|
||||
.SH AUTHORS
|
||||
Jerry Lundström, DNS-OARC
|
||||
.LP
|
||||
Maintained by DNS-OARC
|
||||
.LP
|
||||
.RS
|
||||
.I https://www.dns-oarc.net/
|
||||
.RE
|
||||
.LP
|
||||
.SH BUGS
|
||||
For issues and feature requests please use:
|
||||
.LP
|
||||
.RS
|
||||
\fI@PACKAGE_URL@\fP
|
||||
.RE
|
||||
.LP
|
||||
For question and help please use:
|
||||
.LP
|
||||
.RS
|
||||
\fI@PACKAGE_BUGREPORT@\fP
|
||||
.RE
|
||||
.LP
|
696
plugins/rssm/rssm.c
Normal file
696
plugins/rssm/rssm.c
Normal file
|
@ -0,0 +1,696 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2021, OARC, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <memory.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <arpa/nameser.h>
|
||||
#if HAVE_ARPA_NAMESER_COMPAT_H
|
||||
#include <arpa/nameser_compat.h>
|
||||
#endif
|
||||
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
|
||||
#include <ldns/ldns.h>
|
||||
|
||||
#include "dnscap_common.h"
|
||||
|
||||
#include "hashtbl.h"
|
||||
|
||||
static logerr_t* logerr;
|
||||
static my_bpftimeval open_ts;
|
||||
static my_bpftimeval close_ts;
|
||||
#define COUNTS_PREFIX_DEFAULT "rssm"
|
||||
static char* counts_prefix = 0;
|
||||
static char* sources_prefix = 0;
|
||||
static char* aggregated_prefix = 0;
|
||||
static int dont_fork_on_close = 0;
|
||||
static int sources_into_counters = 0;
|
||||
static int aggregated_into_counters = 0;
|
||||
static char* service_name = 0;
|
||||
static int rssac002v3_yaml = 0;
|
||||
|
||||
output_t rssm_output;
|
||||
|
||||
#define MAX_SIZE_INDEX 4096
|
||||
#define MSG_SIZE_SHIFT 4
|
||||
#define MAX_TBL_ADDRS 2000000
|
||||
#define MAX_TBL_ADDRS2 200000
|
||||
#define MAX_RCODE (1 << 12)
|
||||
|
||||
typedef struct {
|
||||
hashtbl* tbl;
|
||||
iaddr addrs[MAX_TBL_ADDRS];
|
||||
uint64_t count[MAX_TBL_ADDRS];
|
||||
unsigned int num_addrs;
|
||||
} my_hashtbl;
|
||||
|
||||
typedef struct {
|
||||
hashtbl* tbl;
|
||||
iaddr addrs[MAX_TBL_ADDRS2];
|
||||
uint64_t count[MAX_TBL_ADDRS2];
|
||||
unsigned int num_addrs;
|
||||
} my_hashtbl2;
|
||||
|
||||
struct {
|
||||
uint64_t dns_udp_queries_received_ipv4;
|
||||
uint64_t dns_udp_queries_received_ipv6;
|
||||
uint64_t dns_tcp_queries_received_ipv4;
|
||||
uint64_t dns_tcp_queries_received_ipv6;
|
||||
uint64_t dns_udp_responses_sent_ipv4;
|
||||
uint64_t dns_udp_responses_sent_ipv6;
|
||||
uint64_t dns_tcp_responses_sent_ipv4;
|
||||
uint64_t dns_tcp_responses_sent_ipv6;
|
||||
uint64_t udp_query_size[MAX_SIZE_INDEX];
|
||||
uint64_t tcp_query_size[MAX_SIZE_INDEX];
|
||||
uint64_t udp_response_size[MAX_SIZE_INDEX];
|
||||
uint64_t tcp_response_size[MAX_SIZE_INDEX];
|
||||
uint64_t rcodes[MAX_RCODE];
|
||||
my_hashtbl sources;
|
||||
my_hashtbl2 aggregated;
|
||||
uint64_t num_ipv4_sources;
|
||||
uint64_t num_ipv6_sources;
|
||||
} counts;
|
||||
|
||||
static unsigned int
|
||||
iaddr_hash(const void* key)
|
||||
{
|
||||
const iaddr* ia = (const iaddr*)key;
|
||||
|
||||
if (AF_INET == ia->af)
|
||||
return ia->u.a4.s_addr >> 8;
|
||||
else if (AF_INET6 == ia->af) {
|
||||
uint16_t* h = (uint16_t*)&ia->u;
|
||||
return h[2] + h[3] + h[4];
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iaddr_cmp(const void* _a, const void* _b)
|
||||
{
|
||||
const iaddr *a = (const iaddr*)_a, *b = (const iaddr*)_b;
|
||||
|
||||
if (a->af == b->af) {
|
||||
if (AF_INET == a->af)
|
||||
return memcmp(&a->u.a4.s_addr, &b->u.a4.s_addr, sizeof(a->u.a4.s_addr));
|
||||
if (AF_INET6 == a->af)
|
||||
return memcmp(&a->u.a6.s6_addr, &b->u.a6.s6_addr, sizeof(a->u.a6.s6_addr));
|
||||
return 0;
|
||||
}
|
||||
if (a->af < b->af)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ia_str_t ia_str = 0;
|
||||
|
||||
void rssm_extension(int ext, void* arg)
|
||||
{
|
||||
switch (ext) {
|
||||
case DNSCAP_EXT_IA_STR:
|
||||
ia_str = (ia_str_t)arg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rssm_usage()
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\nrssm.so options:\n"
|
||||
"\t-? print these instructions and exit\n"
|
||||
"\t-w <name> write basic counters to <name>.<timesec>.<timeusec>\n"
|
||||
"\t-Y use RSSAC002v3 YAML format when writing counters, the\n"
|
||||
"\t file will contain multiple YAML documents, one for each\n"
|
||||
"\t RSSAC002v3 metric\n"
|
||||
"\t Used with; -S adds custom metric \"dnscap-rssm-sources\"\n"
|
||||
"\t and -A adds \"dnscap-rssm-aggregated-sources\"\n"
|
||||
"\t-n <name> the service name to use in RSSAC002v3 YAML\n"
|
||||
"\t-S write source IPs into counters file with the prefix\n"
|
||||
"\t \"source\" or ...\n"
|
||||
"\t-s <name> write source IPs to <name>.<timesec>.<timeusec>\n"
|
||||
"\t-A write aggregated IPv6(/64) sources into counters file\n"
|
||||
"\t with the prefix \"aggregated-source\" or ...\n"
|
||||
"\t-a <name> write aggregated IPv6(/64) sources to\n"
|
||||
"\t <name>.<timesec>.<timeusec>\n"
|
||||
"\t-D don't fork on close\n");
|
||||
}
|
||||
|
||||
void rssm_getopt(int* argc, char** argv[])
|
||||
{
|
||||
int c;
|
||||
while ((c = getopt(*argc, *argv, "?w:Yn:Ss:Aa:D")) != EOF) {
|
||||
switch (c) {
|
||||
case 'w':
|
||||
if (counts_prefix)
|
||||
free(counts_prefix);
|
||||
counts_prefix = strdup(optarg);
|
||||
break;
|
||||
case 'Y':
|
||||
rssac002v3_yaml = 1;
|
||||
break;
|
||||
case 'n':
|
||||
if (service_name)
|
||||
free(service_name);
|
||||
service_name = strdup(optarg);
|
||||
break;
|
||||
case 'S':
|
||||
sources_into_counters = 1;
|
||||
break;
|
||||
case 's':
|
||||
if (sources_prefix)
|
||||
free(sources_prefix);
|
||||
sources_prefix = strdup(optarg);
|
||||
break;
|
||||
case 'A':
|
||||
aggregated_into_counters = 1;
|
||||
break;
|
||||
case 'a':
|
||||
if (aggregated_prefix)
|
||||
free(aggregated_prefix);
|
||||
aggregated_prefix = strdup(optarg);
|
||||
break;
|
||||
case 'D':
|
||||
dont_fork_on_close = 1;
|
||||
break;
|
||||
case '?':
|
||||
rssm_usage();
|
||||
if (!optopt || optopt == '?') {
|
||||
exit(0);
|
||||
}
|
||||
// fallthrough
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (sources_into_counters && sources_prefix) {
|
||||
fprintf(stderr, "rssm: -S and -s can not be used at the same time!\n");
|
||||
rssm_usage();
|
||||
exit(1);
|
||||
}
|
||||
if (aggregated_into_counters && aggregated_prefix) {
|
||||
fprintf(stderr, "rssm: -A and -a can not be used at the same time!\n");
|
||||
rssm_usage();
|
||||
exit(1);
|
||||
}
|
||||
if (rssac002v3_yaml && !service_name) {
|
||||
fprintf(stderr, "rssm: service name (-n) needed for RSSAC002v3 YAML (-Y) output!\n");
|
||||
rssm_usage();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int rssm_start(logerr_t* a_logerr)
|
||||
{
|
||||
logerr = a_logerr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rssm_stop()
|
||||
{
|
||||
}
|
||||
|
||||
int rssm_open(my_bpftimeval ts)
|
||||
{
|
||||
open_ts = ts;
|
||||
if (counts.sources.tbl)
|
||||
hash_destroy(counts.sources.tbl);
|
||||
if (counts.aggregated.tbl)
|
||||
hash_destroy(counts.aggregated.tbl);
|
||||
memset(&counts, 0, sizeof(counts));
|
||||
if (!(counts.sources.tbl = hash_create(65536, iaddr_hash, iaddr_cmp, 0))) {
|
||||
return -1;
|
||||
}
|
||||
if (!(counts.aggregated.tbl = hash_create(4096, iaddr_hash, iaddr_cmp, 0))) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rssm_save_counts(const char* sbuf)
|
||||
{
|
||||
FILE* fp;
|
||||
int i;
|
||||
char* tbuf = 0;
|
||||
i = asprintf(&tbuf, "%s.%s.%06lu", counts_prefix ? counts_prefix : COUNTS_PREFIX_DEFAULT, sbuf, (u_long)open_ts.tv_usec);
|
||||
if (i < 1 || !tbuf) {
|
||||
logerr("asprintf: out of memory");
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "rssm: saving counts in %s\n", tbuf);
|
||||
fp = fopen(tbuf, "w");
|
||||
if (!fp) {
|
||||
logerr("%s: %s", sbuf, strerror(errno));
|
||||
free(tbuf);
|
||||
return;
|
||||
}
|
||||
if (rssac002v3_yaml) {
|
||||
char tz[21];
|
||||
struct tm tm;
|
||||
|
||||
gmtime_r((time_t*)&open_ts.tv_sec, &tm);
|
||||
if (!strftime(tz, sizeof(tz), "%Y-%m-%dT%H:%M:%SZ", &tm)) {
|
||||
logerr("rssm: strftime failed");
|
||||
fclose(fp);
|
||||
free(tbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(fp, "---\nversion: rssac002v3\nservice: %s\nstart-period: %s\nmetric: traffic-volume\n", service_name, tz);
|
||||
fprintf(fp, "dns-udp-queries-received-ipv4: %" PRIu64 "\n", counts.dns_udp_queries_received_ipv4);
|
||||
fprintf(fp, "dns-udp-queries-received-ipv6: %" PRIu64 "\n", counts.dns_udp_queries_received_ipv6);
|
||||
fprintf(fp, "dns-tcp-queries-received-ipv4: %" PRIu64 "\n", counts.dns_tcp_queries_received_ipv4);
|
||||
fprintf(fp, "dns-tcp-queries-received-ipv6: %" PRIu64 "\n", counts.dns_tcp_queries_received_ipv6);
|
||||
fprintf(fp, "dns-udp-responses-sent-ipv4: %" PRIu64 "\n", counts.dns_udp_responses_sent_ipv4);
|
||||
fprintf(fp, "dns-udp-responses-sent-ipv6: %" PRIu64 "\n", counts.dns_udp_responses_sent_ipv6);
|
||||
fprintf(fp, "dns-tcp-responses-sent-ipv4: %" PRIu64 "\n", counts.dns_tcp_responses_sent_ipv4);
|
||||
fprintf(fp, "dns-tcp-responses-sent-ipv6: %" PRIu64 "\n", counts.dns_tcp_responses_sent_ipv6);
|
||||
|
||||
fprintf(fp, "\n---\nversion: rssac002v3\nservice: %s\nstart-period: %s\nmetric: traffic-sizes\n", service_name, tz);
|
||||
i = 0;
|
||||
for (; i < MAX_SIZE_INDEX; i++) {
|
||||
if (counts.udp_query_size[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < MAX_SIZE_INDEX) {
|
||||
fprintf(fp, "udp-request-sizes:\n");
|
||||
for (; i < MAX_SIZE_INDEX; i++) {
|
||||
if (counts.udp_query_size[i]) {
|
||||
fprintf(fp, " %d-%d: %" PRIu64 "\n",
|
||||
i << MSG_SIZE_SHIFT,
|
||||
((i + 1) << MSG_SIZE_SHIFT) - 1,
|
||||
counts.udp_query_size[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(fp, "udp-request-sizes: {}\n");
|
||||
}
|
||||
i = 0;
|
||||
for (; i < MAX_SIZE_INDEX; i++) {
|
||||
if (counts.udp_response_size[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < MAX_SIZE_INDEX) {
|
||||
fprintf(fp, "udp-response-sizes:\n");
|
||||
for (; i < MAX_SIZE_INDEX; i++) {
|
||||
if (counts.udp_response_size[i]) {
|
||||
fprintf(fp, " %d-%d: %" PRIu64 "\n",
|
||||
i << MSG_SIZE_SHIFT,
|
||||
((i + 1) << MSG_SIZE_SHIFT) - 1,
|
||||
counts.udp_response_size[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(fp, "udp-response-sizes: {}\n");
|
||||
}
|
||||
i = 0;
|
||||
for (; i < MAX_SIZE_INDEX; i++) {
|
||||
if (counts.tcp_query_size[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < MAX_SIZE_INDEX) {
|
||||
fprintf(fp, "tcp-request-sizes:\n");
|
||||
for (; i < MAX_SIZE_INDEX; i++) {
|
||||
if (counts.tcp_query_size[i]) {
|
||||
fprintf(fp, " %d-%d: %" PRIu64 "\n",
|
||||
i << MSG_SIZE_SHIFT,
|
||||
((i + 1) << MSG_SIZE_SHIFT) - 1,
|
||||
counts.tcp_query_size[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(fp, "tcp-request-sizes: {}\n");
|
||||
}
|
||||
i = 0;
|
||||
for (; i < MAX_SIZE_INDEX; i++) {
|
||||
if (counts.tcp_response_size[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < MAX_SIZE_INDEX) {
|
||||
fprintf(fp, "tcp-response-sizes:\n");
|
||||
for (; i < MAX_SIZE_INDEX; i++) {
|
||||
if (counts.tcp_response_size[i]) {
|
||||
fprintf(fp, " %d-%d: %" PRIu64 "\n",
|
||||
i << MSG_SIZE_SHIFT,
|
||||
((i + 1) << MSG_SIZE_SHIFT) - 1,
|
||||
counts.tcp_response_size[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(fp, "tcp-response-sizes: {}\n");
|
||||
}
|
||||
|
||||
fprintf(fp, "\n---\nversion: rssac002v3\nservice: %s\nstart-period: %s\nmetric: rcode-volume\n", service_name, tz);
|
||||
for (i = 0; i < MAX_RCODE; i++) {
|
||||
if (counts.rcodes[i]) {
|
||||
fprintf(fp, "%d: %" PRIu64 "\n", i, counts.rcodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fp, "\n---\nversion: rssac002v3\nservice: %s\nstart-period: %s\nmetric: unique-sources\n", service_name, tz);
|
||||
fprintf(fp, "num-sources-ipv4: %" PRIu64 "\n", counts.num_ipv4_sources);
|
||||
fprintf(fp, "num-sources-ipv6: %" PRIu64 "\n", counts.num_ipv6_sources);
|
||||
fprintf(fp, "num-sources-ipv6-aggregate: %u\n", counts.aggregated.num_addrs);
|
||||
|
||||
if (sources_into_counters) {
|
||||
fprintf(fp, "\n---\nversion: rssac002v3\nservice: %s\nstart-period: %s\nmetric: dnscap-rssm-sources\n", service_name, tz);
|
||||
if (counts.sources.num_addrs) {
|
||||
fprintf(fp, "sources:\n");
|
||||
for (i = 0; i < counts.sources.num_addrs; i++) {
|
||||
fprintf(fp, " %s: %" PRIu64 "\n", ia_str(counts.sources.addrs[i]), counts.sources.count[i]);
|
||||
}
|
||||
} else {
|
||||
fprintf(fp, "sources: {}\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (aggregated_into_counters) {
|
||||
fprintf(fp, "\n---\nversion: rssac002v3\nservice: %s\nstart-period: %s\nmetric: dnscap-rssm-aggregated-sources\n", service_name, tz);
|
||||
if (counts.aggregated.num_addrs) {
|
||||
fprintf(fp, "aggregated-sources:\n");
|
||||
for (i = 0; i < counts.aggregated.num_addrs; i++) {
|
||||
fprintf(fp, " %s: %" PRIu64 "\n", ia_str(counts.aggregated.addrs[i]), counts.aggregated.count[i]);
|
||||
}
|
||||
} else {
|
||||
fprintf(fp, "aggregated-sources: {}\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(fp, "first-packet-time %ld\n", (long)open_ts.tv_sec);
|
||||
fprintf(fp, "last-packet-time %ld\n", (long)close_ts.tv_sec);
|
||||
fprintf(fp, "dns-udp-queries-received-ipv4 %" PRIu64 "\n", counts.dns_udp_queries_received_ipv4);
|
||||
fprintf(fp, "dns-udp-queries-received-ipv6 %" PRIu64 "\n", counts.dns_udp_queries_received_ipv6);
|
||||
fprintf(fp, "dns-tcp-queries-received-ipv4 %" PRIu64 "\n", counts.dns_tcp_queries_received_ipv4);
|
||||
fprintf(fp, "dns-tcp-queries-received-ipv6 %" PRIu64 "\n", counts.dns_tcp_queries_received_ipv6);
|
||||
fprintf(fp, "dns-udp-responses-sent-ipv4 %" PRIu64 "\n", counts.dns_udp_responses_sent_ipv4);
|
||||
fprintf(fp, "dns-udp-responses-sent-ipv6 %" PRIu64 "\n", counts.dns_udp_responses_sent_ipv6);
|
||||
fprintf(fp, "dns-tcp-responses-sent-ipv4 %" PRIu64 "\n", counts.dns_tcp_responses_sent_ipv4);
|
||||
fprintf(fp, "dns-tcp-responses-sent-ipv6 %" PRIu64 "\n", counts.dns_tcp_responses_sent_ipv6);
|
||||
for (i = 0; i < MAX_SIZE_INDEX; i++)
|
||||
if (counts.udp_query_size[i])
|
||||
fprintf(fp, "dns-udp-query-size %d-%d %" PRIu64 "\n",
|
||||
i << MSG_SIZE_SHIFT,
|
||||
((i + 1) << MSG_SIZE_SHIFT) - 1,
|
||||
counts.udp_query_size[i]);
|
||||
for (i = 0; i < MAX_SIZE_INDEX; i++)
|
||||
if (counts.tcp_query_size[i])
|
||||
fprintf(fp, "dns-tcp-query-size %d-%d %" PRIu64 "\n",
|
||||
i << MSG_SIZE_SHIFT,
|
||||
((i + 1) << MSG_SIZE_SHIFT) - 1,
|
||||
counts.tcp_query_size[i]);
|
||||
for (i = 0; i < MAX_SIZE_INDEX; i++)
|
||||
if (counts.udp_response_size[i])
|
||||
fprintf(fp, "dns-udp-response-size %d-%d %" PRIu64 "\n",
|
||||
i << MSG_SIZE_SHIFT,
|
||||
((i + 1) << MSG_SIZE_SHIFT) - 1,
|
||||
counts.udp_response_size[i]);
|
||||
for (i = 0; i < MAX_SIZE_INDEX; i++)
|
||||
if (counts.tcp_response_size[i])
|
||||
fprintf(fp, "dns-tcp-response-size %d-%d %" PRIu64 "\n",
|
||||
i << MSG_SIZE_SHIFT,
|
||||
((i + 1) << MSG_SIZE_SHIFT) - 1,
|
||||
counts.tcp_response_size[i]);
|
||||
for (i = 0; i < MAX_RCODE; i++)
|
||||
if (counts.rcodes[i])
|
||||
fprintf(fp, "dns-rcode %d %" PRIu64 "\n",
|
||||
i, counts.rcodes[i]);
|
||||
fprintf(fp, "num-sources %u\n", counts.sources.num_addrs);
|
||||
if (sources_into_counters) {
|
||||
for (i = 0; i < counts.sources.num_addrs; i++) {
|
||||
fprintf(fp, "source %s %" PRIu64 "\n", ia_str(counts.sources.addrs[i]), counts.sources.count[i]);
|
||||
}
|
||||
}
|
||||
if (aggregated_into_counters) {
|
||||
for (i = 0; i < counts.aggregated.num_addrs; i++) {
|
||||
fprintf(fp, "aggregated-source %s %" PRIu64 "\n", ia_str(counts.aggregated.addrs[i]), counts.aggregated.count[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
fprintf(stderr, "rssm: done\n");
|
||||
free(tbuf);
|
||||
}
|
||||
|
||||
void rssm_save_sources(const char* sbuf)
|
||||
{
|
||||
FILE* fp;
|
||||
char* tbuf = 0;
|
||||
int i;
|
||||
i = asprintf(&tbuf, "%s.%s.%06lu", sources_prefix, sbuf, (u_long)open_ts.tv_usec);
|
||||
if (i < 1 || !tbuf) {
|
||||
logerr("asprintf: out of memory");
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "rssm: saving %u sources in %s\n", counts.sources.num_addrs, tbuf);
|
||||
fp = fopen(tbuf, "w");
|
||||
if (!fp) {
|
||||
logerr("%s: %s", tbuf, strerror(errno));
|
||||
free(tbuf);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < counts.sources.num_addrs; i++) {
|
||||
fprintf(fp, "%s %" PRIu64 "\n", ia_str(counts.sources.addrs[i]), counts.sources.count[i]);
|
||||
}
|
||||
fclose(fp);
|
||||
fprintf(stderr, "rssm: done\n");
|
||||
free(tbuf);
|
||||
}
|
||||
|
||||
void rssm_save_aggregated(const char* sbuf)
|
||||
{
|
||||
FILE* fp;
|
||||
char* tbuf = 0;
|
||||
int i;
|
||||
i = asprintf(&tbuf, "%s.%s.%06lu", aggregated_prefix, sbuf, (u_long)open_ts.tv_usec);
|
||||
if (i < 1 || !tbuf) {
|
||||
logerr("asprintf: out of memory");
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "rssm: saving %u aggregated in %s\n", counts.aggregated.num_addrs, tbuf);
|
||||
fp = fopen(tbuf, "w");
|
||||
if (!fp) {
|
||||
logerr("%s: %s", tbuf, strerror(errno));
|
||||
free(tbuf);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < counts.aggregated.num_addrs; i++) {
|
||||
fprintf(fp, "%s %" PRIu64 "\n", ia_str(counts.aggregated.addrs[i]), counts.aggregated.count[i]);
|
||||
}
|
||||
fclose(fp);
|
||||
fprintf(stderr, "rssm: done\n");
|
||||
free(tbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fork a separate process so that we don't block the main dnscap. Use double-fork
|
||||
* to avoid zombies for the main dnscap process.
|
||||
*/
|
||||
int rssm_close(my_bpftimeval ts)
|
||||
{
|
||||
char sbuf[265];
|
||||
pid_t pid;
|
||||
struct tm tm;
|
||||
|
||||
if (dont_fork_on_close) {
|
||||
struct tm tm;
|
||||
gmtime_r((time_t*)&open_ts.tv_sec, &tm);
|
||||
strftime(sbuf, sizeof(sbuf), "%Y%m%d.%H%M%S", &tm);
|
||||
close_ts = ts;
|
||||
rssm_save_counts(sbuf);
|
||||
if (sources_prefix)
|
||||
rssm_save_sources(sbuf);
|
||||
if (aggregated_prefix)
|
||||
rssm_save_aggregated(sbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
logerr("rssm.so: fork: %s", strerror(errno));
|
||||
return 1;
|
||||
} else if (pid) {
|
||||
/* parent */
|
||||
waitpid(pid, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
/* 1st gen child continues */
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
logerr("rssm.so: fork: %s", strerror(errno));
|
||||
return 1;
|
||||
} else if (pid) {
|
||||
/* 1st gen child exits */
|
||||
exit(0);
|
||||
}
|
||||
/* grandchild (2nd gen) continues */
|
||||
gmtime_r((time_t*)&open_ts.tv_sec, &tm);
|
||||
strftime(sbuf, sizeof(sbuf), "%Y%m%d.%H%M%S", &tm);
|
||||
close_ts = ts;
|
||||
rssm_save_counts(sbuf);
|
||||
if (sources_prefix)
|
||||
rssm_save_sources(sbuf);
|
||||
if (aggregated_prefix)
|
||||
rssm_save_aggregated(sbuf);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
find_or_add(iaddr ia)
|
||||
{
|
||||
uint64_t* c = hash_find(&ia, counts.sources.tbl);
|
||||
if (c) {
|
||||
(*c)++;
|
||||
} else {
|
||||
if (counts.sources.num_addrs == MAX_TBL_ADDRS)
|
||||
return;
|
||||
counts.sources.addrs[counts.sources.num_addrs] = ia;
|
||||
if (hash_add(&counts.sources.addrs[counts.sources.num_addrs], &counts.sources.count[counts.sources.num_addrs], counts.sources.tbl)) {
|
||||
logerr("rssm.so: unable to add address to hash");
|
||||
return;
|
||||
}
|
||||
counts.sources.count[counts.sources.num_addrs]++;
|
||||
counts.sources.num_addrs++;
|
||||
if (ia.af == AF_INET) {
|
||||
counts.num_ipv4_sources++;
|
||||
} else {
|
||||
counts.num_ipv6_sources++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ia.af == AF_INET6) {
|
||||
iaddr v6agg = ia;
|
||||
|
||||
memset(((uint8_t*)&v6agg.u.a6) + 8, 0, 8);
|
||||
c = hash_find(&v6agg, counts.aggregated.tbl);
|
||||
if (c) {
|
||||
(*c)++;
|
||||
} else {
|
||||
if (counts.aggregated.num_addrs == MAX_TBL_ADDRS2)
|
||||
return;
|
||||
counts.aggregated.addrs[counts.aggregated.num_addrs] = v6agg;
|
||||
if (hash_add(&counts.aggregated.addrs[counts.aggregated.num_addrs], &counts.aggregated.count[counts.aggregated.num_addrs], counts.aggregated.tbl)) {
|
||||
logerr("rssm.so: unable to add aggregated address to hash");
|
||||
return;
|
||||
}
|
||||
counts.aggregated.count[counts.aggregated.num_addrs]++;
|
||||
counts.aggregated.num_addrs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rssm_output(const char* descr, iaddr from, iaddr to, uint8_t proto, unsigned flags,
|
||||
unsigned sport, unsigned dport, my_bpftimeval ts,
|
||||
const u_char* pkt_copy, const unsigned olen,
|
||||
const u_char* payload, const unsigned payloadlen)
|
||||
{
|
||||
unsigned dnslen;
|
||||
ldns_pkt* pkt = 0;
|
||||
|
||||
if (!(flags & DNSCAP_OUTPUT_ISDNS))
|
||||
return;
|
||||
|
||||
if (ldns_wire2pkt(&pkt, payload, payloadlen) != LDNS_STATUS_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
dnslen = payloadlen >> MSG_SIZE_SHIFT;
|
||||
if (dnslen >= MAX_SIZE_INDEX)
|
||||
dnslen = MAX_SIZE_INDEX - 1;
|
||||
|
||||
if (!ldns_pkt_qr(pkt)) {
|
||||
find_or_add(from);
|
||||
if (IPPROTO_UDP == proto) {
|
||||
counts.udp_query_size[dnslen]++;
|
||||
} else if (IPPROTO_TCP == proto) {
|
||||
counts.tcp_query_size[dnslen]++;
|
||||
}
|
||||
if (AF_INET == from.af) {
|
||||
if (IPPROTO_UDP == proto) {
|
||||
counts.dns_udp_queries_received_ipv4++;
|
||||
} else if (IPPROTO_TCP == proto) {
|
||||
counts.dns_tcp_queries_received_ipv4++;
|
||||
}
|
||||
} else if (AF_INET6 == from.af) {
|
||||
if (IPPROTO_UDP == proto) {
|
||||
counts.dns_udp_queries_received_ipv6++;
|
||||
} else if (IPPROTO_TCP == proto) {
|
||||
counts.dns_tcp_queries_received_ipv6++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint16_t rcode = ldns_pkt_get_rcode(pkt);
|
||||
if (IPPROTO_UDP == proto) {
|
||||
counts.udp_response_size[dnslen]++;
|
||||
} else if (IPPROTO_TCP == proto) {
|
||||
counts.tcp_response_size[dnslen]++;
|
||||
}
|
||||
if (AF_INET == from.af) {
|
||||
if (IPPROTO_UDP == proto) {
|
||||
counts.dns_udp_responses_sent_ipv4++;
|
||||
} else if (IPPROTO_TCP == proto) {
|
||||
counts.dns_tcp_responses_sent_ipv4++;
|
||||
}
|
||||
} else if (AF_INET6 == from.af) {
|
||||
if (IPPROTO_UDP == proto) {
|
||||
counts.dns_udp_responses_sent_ipv6++;
|
||||
} else if (IPPROTO_TCP == proto) {
|
||||
counts.dns_tcp_responses_sent_ipv6++;
|
||||
}
|
||||
}
|
||||
if (ldns_pkt_arcount(pkt)) {
|
||||
rcode |= ((uint16_t)ldns_pkt_edns_extended_rcode(pkt) << 4);
|
||||
}
|
||||
counts.rcodes[rcode]++;
|
||||
}
|
||||
|
||||
ldns_pkt_free(pkt);
|
||||
}
|
58
plugins/rssm/test1.gold
Normal file
58
plugins/rssm/test1.gold
Normal file
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
version: rssac002v3
|
||||
service: test1
|
||||
start-period: 2016-10-20T15:23:01Z
|
||||
metric: traffic-volume
|
||||
dns-udp-queries-received-ipv4: 41
|
||||
dns-udp-queries-received-ipv6: 0
|
||||
dns-tcp-queries-received-ipv4: 0
|
||||
dns-tcp-queries-received-ipv6: 0
|
||||
dns-udp-responses-sent-ipv4: 41
|
||||
dns-udp-responses-sent-ipv6: 0
|
||||
dns-tcp-responses-sent-ipv4: 0
|
||||
dns-tcp-responses-sent-ipv6: 0
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test1
|
||||
start-period: 2016-10-20T15:23:01Z
|
||||
metric: traffic-sizes
|
||||
udp-request-sizes:
|
||||
16-31: 24
|
||||
32-47: 17
|
||||
udp-response-sizes:
|
||||
176-191: 24
|
||||
256-271: 17
|
||||
tcp-request-sizes: {}
|
||||
tcp-response-sizes: {}
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test1
|
||||
start-period: 2016-10-20T15:23:01Z
|
||||
metric: rcode-volume
|
||||
0: 41
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test1
|
||||
start-period: 2016-10-20T15:23:01Z
|
||||
metric: unique-sources
|
||||
num-sources-ipv4: 1
|
||||
num-sources-ipv6: 0
|
||||
num-sources-ipv6-aggregate: 0
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test1
|
||||
start-period: 2016-10-20T15:23:01Z
|
||||
metric: dnscap-rssm-sources
|
||||
sources:
|
||||
172.17.0.10: 41
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test1
|
||||
start-period: 2016-10-20T15:23:01Z
|
||||
metric: dnscap-rssm-aggregated-sources
|
||||
aggregated-sources: {}
|
11
plugins/rssm/test1.sh
Executable file
11
plugins/rssm/test1.sh
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh -xe
|
||||
|
||||
plugin=`find . -name 'rssm.so' | head -n 1`
|
||||
if [ -z "$plugin" ]; then
|
||||
echo "Unable to find the RSSM plugin"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
../../src/dnscap -N -T -r "$srcdir/../../src/test/dns.pcap" -P "$plugin" -w test1 -Y -n test1 -A -S -D
|
||||
|
||||
diff test1.20161020.152301.075993 "$srcdir/test1.gold"
|
43
plugins/rssm/test2.gold
Normal file
43
plugins/rssm/test2.gold
Normal file
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
0: 123
|
||||
metric: rcode-volume
|
||||
service: test1
|
||||
start-period: 2016-10-20T15:23:01Z
|
||||
version: rssac002v3
|
||||
|
||||
---
|
||||
metric: traffic-sizes
|
||||
service: test1
|
||||
start-period: 2016-10-20T15:23:01Z
|
||||
tcp-request-sizes: {}
|
||||
tcp-response-sizes: {}
|
||||
udp-request-sizes:
|
||||
16-31: 72
|
||||
32-47: 51
|
||||
udp-response-sizes:
|
||||
176-191: 72
|
||||
256-271: 51
|
||||
version: rssac002v3
|
||||
|
||||
---
|
||||
dns-tcp-queries-received-ipv4: 0
|
||||
dns-tcp-queries-received-ipv6: 0
|
||||
dns-tcp-responses-sent-ipv4: 0
|
||||
dns-tcp-responses-sent-ipv6: 0
|
||||
dns-udp-queries-received-ipv4: 123
|
||||
dns-udp-queries-received-ipv6: 0
|
||||
dns-udp-responses-sent-ipv4: 123
|
||||
dns-udp-responses-sent-ipv6: 0
|
||||
metric: traffic-volume
|
||||
service: test1
|
||||
start-period: 2016-10-20T15:23:01Z
|
||||
version: rssac002v3
|
||||
|
||||
---
|
||||
metric: unique-sources
|
||||
num-sources-ipv4: 1
|
||||
num-sources-ipv6: 0
|
||||
num-sources-ipv6-aggregate: 0
|
||||
service: test1
|
||||
start-period: 2016-10-20T15:23:01Z
|
||||
version: rssac002v3
|
5
plugins/rssm/test2.sh
Executable file
5
plugins/rssm/test2.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh -xe
|
||||
|
||||
"$srcdir"/dnscap-rssm-rssac002 --sort "$srcdir/test1.gold" "$srcdir/test1.gold" "$srcdir/test1.gold" > test2.out
|
||||
|
||||
diff test2.out "$srcdir/test2.gold"
|
57
plugins/rssm/test3.gold
Normal file
57
plugins/rssm/test3.gold
Normal file
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
version: rssac002v3
|
||||
service: test3
|
||||
start-period: 2018-11-27T15:52:00Z
|
||||
metric: traffic-volume
|
||||
dns-udp-queries-received-ipv4: 0
|
||||
dns-udp-queries-received-ipv6: 1
|
||||
dns-tcp-queries-received-ipv4: 0
|
||||
dns-tcp-queries-received-ipv6: 0
|
||||
dns-udp-responses-sent-ipv4: 0
|
||||
dns-udp-responses-sent-ipv6: 1
|
||||
dns-tcp-responses-sent-ipv4: 0
|
||||
dns-tcp-responses-sent-ipv6: 0
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test3
|
||||
start-period: 2018-11-27T15:52:00Z
|
||||
metric: traffic-sizes
|
||||
udp-request-sizes:
|
||||
32-47: 1
|
||||
udp-response-sizes:
|
||||
48-63: 1
|
||||
tcp-request-sizes: {}
|
||||
tcp-response-sizes: {}
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test3
|
||||
start-period: 2018-11-27T15:52:00Z
|
||||
metric: rcode-volume
|
||||
0: 1
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test3
|
||||
start-period: 2018-11-27T15:52:00Z
|
||||
metric: unique-sources
|
||||
num-sources-ipv4: 0
|
||||
num-sources-ipv6: 1
|
||||
num-sources-ipv6-aggregate: 1
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test3
|
||||
start-period: 2018-11-27T15:52:00Z
|
||||
metric: dnscap-rssm-sources
|
||||
sources:
|
||||
2a01:3f0:0:57::245: 1
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test3
|
||||
start-period: 2018-11-27T15:52:00Z
|
||||
metric: dnscap-rssm-aggregated-sources
|
||||
aggregated-sources:
|
||||
2a01:3f0:0:57::: 1
|
11
plugins/rssm/test3.sh
Executable file
11
plugins/rssm/test3.sh
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh -xe
|
||||
|
||||
plugin=`find . -name 'rssm.so' | head -n 1`
|
||||
if [ -z "$plugin" ]; then
|
||||
echo "Unable to find the RSSM plugin"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
../../src/dnscap -N -T -r "$srcdir/../../src/test/dns6.pcap" -P "$plugin" -w test3 -Y -n test3 -A -S -D
|
||||
|
||||
diff test3.20181127.155200.414188 "$srcdir/test3.gold"
|
14
plugins/rssm/test4.sh
Executable file
14
plugins/rssm/test4.sh
Executable file
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh -xe
|
||||
|
||||
plugin=`find . -name 'rssm.so' | head -n 1`
|
||||
if [ -z "$plugin" ]; then
|
||||
echo "Unable to find the RSSM plugin"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
../../src/dnscap -r "$srcdir/../../src/test/dns.pcap" -P "$plugin" -?
|
||||
! ../../src/dnscap -r "$srcdir/../../src/test/dns.pcap" -P "$plugin" -X
|
||||
! ../../src/dnscap -r "$srcdir/../../src/test/dns.pcap" -P "$plugin" -s s -s s -S
|
||||
! ../../src/dnscap -r "$srcdir/../../src/test/dns.pcap" -P "$plugin" -a a -a a -A
|
||||
! ../../src/dnscap -r "$srcdir/../../src/test/dns.pcap" -P "$plugin" -Y
|
||||
../../src/dnscap -r "$srcdir/../../src/test/dns.pcap" -P "$plugin" -D -w test4 -w test4 -n n -n n -s test4.src -a test4.agg
|
58
plugins/rssm/test5.gold
Normal file
58
plugins/rssm/test5.gold
Normal file
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
version: rssac002v3
|
||||
service: test5
|
||||
start-period: 2018-01-10T11:22:41Z
|
||||
metric: traffic-volume
|
||||
dns-udp-queries-received-ipv4: 0
|
||||
dns-udp-queries-received-ipv6: 0
|
||||
dns-tcp-queries-received-ipv4: 41
|
||||
dns-tcp-queries-received-ipv6: 0
|
||||
dns-udp-responses-sent-ipv4: 0
|
||||
dns-udp-responses-sent-ipv6: 0
|
||||
dns-tcp-responses-sent-ipv4: 41
|
||||
dns-tcp-responses-sent-ipv6: 0
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test5
|
||||
start-period: 2018-01-10T11:22:41Z
|
||||
metric: traffic-sizes
|
||||
udp-request-sizes: {}
|
||||
udp-response-sizes: {}
|
||||
tcp-request-sizes:
|
||||
16-31: 24
|
||||
32-47: 17
|
||||
tcp-response-sizes:
|
||||
32-47: 24
|
||||
128-143: 17
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test5
|
||||
start-period: 2018-01-10T11:22:41Z
|
||||
metric: rcode-volume
|
||||
0: 41
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test5
|
||||
start-period: 2018-01-10T11:22:41Z
|
||||
metric: unique-sources
|
||||
num-sources-ipv4: 1
|
||||
num-sources-ipv6: 0
|
||||
num-sources-ipv6-aggregate: 0
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test5
|
||||
start-period: 2018-01-10T11:22:41Z
|
||||
metric: dnscap-rssm-sources
|
||||
sources:
|
||||
172.17.0.8: 41
|
||||
|
||||
---
|
||||
version: rssac002v3
|
||||
service: test5
|
||||
start-period: 2018-01-10T11:22:41Z
|
||||
metric: dnscap-rssm-aggregated-sources
|
||||
aggregated-sources: {}
|
11
plugins/rssm/test5.sh
Executable file
11
plugins/rssm/test5.sh
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh -xe
|
||||
|
||||
plugin=`find . -name 'rssm.so' | head -n 1`
|
||||
if [ -z "$plugin" ]; then
|
||||
echo "Unable to find the RSSM plugin"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
../../src/dnscap -N -T -r "$srcdir/../../src/test/dnso1tcp.pcap" -P "$plugin" -w test5 -Y -n test5 -A -S -D
|
||||
|
||||
diff test5.20180110.112241.543825 "$srcdir/test5.gold"
|
Loading…
Add table
Add a link
Reference in a new issue