├── debian
├── compat
├── dirs
├── docs
├── source
│ └── format
├── rules
├── manpages
├── control
├── copyright
└── changelog
├── tests
├── 20190719
│ ├── idn_vs_tld.dat
│ ├── ipv6_rsn_abusers_accum.dat
│ ├── opcode.dat
│ ├── chaos_types_and_names.dat
│ ├── client_subnet_count.dat
│ ├── do_bit.dat
│ ├── idn_qname.dat
│ ├── rcode.dat
│ ├── rd_bit.dat
│ ├── edns_version.dat
│ ├── ipv6_rsn_abusers_count.dat
│ ├── dnssec_qtype.dat
│ ├── client_subnet_accum.dat
│ ├── qtype.dat
│ ├── client_subnet2_count.dat
│ ├── client_subnet2_trace.dat
│ ├── direction_vs_ipproto.dat
│ ├── transport_vs_qtype.dat
│ ├── certain_qnames_vs_qtype.dat
│ ├── pcap_stats.dat
│ ├── edns_bufsiz.dat
│ ├── client_subnet2_accum.dat
│ ├── qtype_vs_tld.dat
│ ├── client_addr_vs_rcode_accum.dat
│ ├── qtype_vs_qnamelen.dat
│ ├── client_port_range.dat
│ └── rcode_vs_replylen.dat
├── dsc-datatool.py
├── test_main.py
├── broken.xml
├── dsc-datatool
├── test.gold4
├── utf8.xml
├── test_objects.py
├── coverage.sh
├── test.sh
├── test.gold3
├── ipv6-unicast-address-assignments.csv
├── test.gold2
├── 1458044657.xml
├── test.gold
├── labler.yaml
└── 1563520620.dscdata.xml
├── sonar-project.properties.local
├── MANIFEST.in
├── setup.cfg
├── .gitignore
├── man
├── man5
│ └── dsc-datatool.conf.5
├── man7
│ ├── dsc-datatool-output-influxdb.7
│ ├── dsc-datatool-transformer-labler.7
│ ├── dsc-datatool-transformer-netremap.7
│ ├── dsc-datatool-generator-client_subnet_country.7
│ ├── dsc-datatool-transformer-reranger.7
│ ├── dsc-datatool-generator-client_subnet_authority.7
│ └── dsc-datatool-output-prometheus.7
└── man1
│ └── dsc-datatool.1
├── setup.py
├── .forgejo
└── workflows
│ └── test.yml
├── .copr
└── Makefile
├── README.md
├── contrib
└── iana-dns-params-toyaml.py
├── LICENSE
├── dsc_datatool
├── transformer
│ ├── labler.py
│ ├── net_remap.py
│ └── re_ranger.py
├── input
│ ├── xml.py
│ └── dat.py
├── output
│ ├── influxdb.py
│ └── prometheus.py
├── generator
│ ├── client_subnet_country.py
│ └── client_subnet_authority.py
└── __init__.py
├── CHANGES
└── rpm
└── dsc-datatool.spec
/debian/compat:
--------------------------------------------------------------------------------
1 | 10
2 |
--------------------------------------------------------------------------------
/debian/dirs:
--------------------------------------------------------------------------------
1 | usr/bin
2 |
--------------------------------------------------------------------------------
/tests/20190719/idn_vs_tld.dat:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/debian/docs:
--------------------------------------------------------------------------------
1 | README.md
2 | CHANGES
3 |
--------------------------------------------------------------------------------
/debian/source/format:
--------------------------------------------------------------------------------
1 | 3.0 (quilt)
2 |
--------------------------------------------------------------------------------
/tests/20190719/ipv6_rsn_abusers_accum.dat:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sonar-project.properties.local:
--------------------------------------------------------------------------------
1 | sonar.sources=dsc_datatool
2 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | graft dsc_datatool
2 | global-exclude *.pyc
3 | include CHANGES
4 |
--------------------------------------------------------------------------------
/tests/20190719/opcode.dat:
--------------------------------------------------------------------------------
1 | 1563520560 0 345
2 | #MD5 3a960c4f0c7ba6d9062f78477f11f1e8
3 |
--------------------------------------------------------------------------------
/tests/20190719/chaos_types_and_names.dat:
--------------------------------------------------------------------------------
1 | 1563520560
2 | #MD5 d0a25752e8594d8c013f127947cbc5f9
3 |
--------------------------------------------------------------------------------
/tests/20190719/client_subnet_count.dat:
--------------------------------------------------------------------------------
1 | 1563520560 2
2 | #MD5 387ea7cf05e936539c3ec40a63d29dbf
3 |
--------------------------------------------------------------------------------
/tests/20190719/do_bit.dat:
--------------------------------------------------------------------------------
1 | 1563520560 set 134 clr 211
2 | #MD5 7bb564b9b0ebd370f10339a349e82e42
3 |
--------------------------------------------------------------------------------
/tests/20190719/idn_qname.dat:
--------------------------------------------------------------------------------
1 | 1563520560 normal 345
2 | #MD5 df6cf377b07e083c57953eda1e9100ae
3 |
--------------------------------------------------------------------------------
/tests/20190719/rcode.dat:
--------------------------------------------------------------------------------
1 | 1563520560 0 416 3 8 2 6
2 | #MD5 7ae0768474205df1d88a4fae8d03b56d
3 |
--------------------------------------------------------------------------------
/tests/20190719/rd_bit.dat:
--------------------------------------------------------------------------------
1 | 1563520560 clr 159 set 186
2 | #MD5 2dd58158fe3ebb4176faabd9199d06fe
3 |
--------------------------------------------------------------------------------
/tests/20190719/edns_version.dat:
--------------------------------------------------------------------------------
1 | 1563520560 0 141 none 204
2 | #MD5 4c2f5b7124dea738c503bb5dccb232e2
3 |
--------------------------------------------------------------------------------
/tests/20190719/ipv6_rsn_abusers_count.dat:
--------------------------------------------------------------------------------
1 | 1563520560 0
2 | #MD5 9b8bcef0308351ed7d24cbed894c2217
3 |
--------------------------------------------------------------------------------
/tests/20190719/dnssec_qtype.dat:
--------------------------------------------------------------------------------
1 | 1563520560 else 315 48 25 43 5
2 | #MD5 2c7018cb7254ee62b7097fcb6239a57d
3 |
--------------------------------------------------------------------------------
/tests/20190719/client_subnet_accum.dat:
--------------------------------------------------------------------------------
1 | 2620:ff:c000:: 5
2 | 64.191.0.0 198
3 | #MD5 7b9f4f6c1fad290e8d9f0f6ef2905b0f
4 |
--------------------------------------------------------------------------------
/tests/20190719/qtype.dat:
--------------------------------------------------------------------------------
1 | 1563520560 12 78 2 7 6 4 15 9 else 48 1 128 28 71
2 | #MD5 afc958bfa6de0678f87f62fe9c9c134f
3 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [tool:pytest]
2 | testpaths = tests
3 |
4 | [coverage:run]
5 | branch = True
6 | source =
7 | dsc_datatool
8 |
--------------------------------------------------------------------------------
/tests/20190719/client_subnet2_count.dat:
--------------------------------------------------------------------------------
1 | 1563520560 rfc1918-ptr 1 ok 2 non-auth-tld 1
2 | #MD5 e883a01b1b022817133db1995aa2c10b
3 |
--------------------------------------------------------------------------------
/tests/20190719/client_subnet2_trace.dat:
--------------------------------------------------------------------------------
1 | 1563520560 non-auth-tld 18 rfc1918-ptr 1 ok 185
2 | #MD5 b4a4ddc379bfe93124277fc6e2c330cb
3 |
--------------------------------------------------------------------------------
/tests/20190719/direction_vs_ipproto.dat:
--------------------------------------------------------------------------------
1 | 1563520560 recv udp:219 sent udp:289 else udp:267
2 | #MD5 425e11a1b3d2f17c5e87e54ff5ecbeb3
3 |
--------------------------------------------------------------------------------
/tests/20190719/transport_vs_qtype.dat:
--------------------------------------------------------------------------------
1 | 1563520560 udp else:48:28:71:1:128:15:9:12:78:2:7:6:4
2 | #MD5 9712453c813073917ee807bfb91dc07a
3 |
--------------------------------------------------------------------------------
/tests/20190719/certain_qnames_vs_qtype.dat:
--------------------------------------------------------------------------------
1 | 1563520560 else else:48:1:128:28:71:15:9:12:78:2:7:6:4
2 | #MD5 4bc33435cfa929c19592fa5bbfd4bb69
3 |
--------------------------------------------------------------------------------
/tests/dsc-datatool.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | import sys
3 | from dsc_datatool import main
4 |
5 | if __name__ == "__main__":
6 | sys.exit(main())
7 |
--------------------------------------------------------------------------------
/tests/20190719/pcap_stats.dat:
--------------------------------------------------------------------------------
1 | 1563520560 filter_received eth0:5625 kernel_dropped eth0:731 pkts_captured eth0:4894
2 | #MD5 6dbbefe12290b8e7f589f86ec9c30556
3 |
--------------------------------------------------------------------------------
/tests/test_main.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import dsc_datatool as app
3 |
4 |
5 | def test_main():
6 | with pytest.raises(Exception):
7 | app.main()
8 |
--------------------------------------------------------------------------------
/tests/broken.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/tests/20190719/qtype_vs_qnamelen.dat:
--------------------------------------------------------------------------------
1 | 2 23 1
2 | 2 9 1
3 | 2 21 2
4 | 2 12 3
5 | 43 26 2
6 | 43 17 1
7 | 43 15 2
8 | 12 28 1
9 | 12 72 2
10 | 12 23 35
11 | 12 26 16
12 | 12 25 21
13 | 12 27 1
14 | 12 24 2
15 | 6 9 1
16 | 6 21 2
17 | 6 17 1
18 | 1 18 1
19 | 1 46 1
20 | 1 12 1
21 | 1 20 84
22 | 1 23 1
23 | 1 16 8
24 | 1 24 2
25 | 1 15 28
26 | 1 22 1
27 | 1 28 1
28 | 28 16 7
29 | 28 24 2
30 | 28 15 12
31 | 28 18 1
32 | 28 35 1
33 | 28 20 45
34 | 28 26 1
35 | 28 23 1
36 | 28 59 1
37 | 48 12 2
38 | 48 13 10
39 | 48 23 11
40 | 48 17 2
41 | 16 74 9
42 | 16 15 1
43 | 16 21 8
44 | 15 26 1
45 | 15 13 8
46 | #MD5 1cf280838630abd4d8cc5fe322bbd8ff
47 |
--------------------------------------------------------------------------------
/man/man5/dsc-datatool.conf.5:
--------------------------------------------------------------------------------
1 | .TH "dsc-datatool.conf" "5"
2 | .SH NAME
3 | dsc-datatool.conf \- Configuration file for dsc-datatool.
4 | .SH DESCRIPTION
5 | Not implemented.
6 | .SH "SEE ALSO"
7 | .BR dsc-datatool (1)
8 | .SH AUTHORS
9 | Jerry Lundström, DNS-OARC
10 | .LP
11 | Maintained by DNS-OARC
12 | .LP
13 | .RS
14 | .I https://www.dns-oarc.net/tools/dsc
15 | .RE
16 | .LP
17 | .SH BUGS
18 | For issues and feature requests please use:
19 | .LP
20 | .RS
21 | \fIhttps://codeberg.org/DNS-OARC/dsc-datatool/issues\fP
22 | .RE
23 | .LP
24 | For question and help please use:
25 | .LP
26 | .RS
27 | \fIhttps://chat.dns-oarc.net/community/channels/oarc-software\fP
28 | .RE
29 | .LP
30 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import find_packages, setup
2 |
3 | setup(
4 | name='dsc_datatool',
5 | version='1.4.2',
6 | packages=find_packages(),
7 | include_package_data=True,
8 | zip_safe=False,
9 | python_requires='>=3.5.1',
10 | install_requires=[
11 | 'maxminddb>=1.2.0',
12 | 'PyYAML>=3.11',
13 | ],
14 | extras_require={
15 | 'dev': [
16 | 'pytest>=4',
17 | 'coverage',
18 | 'watchdog',
19 | ],
20 | },
21 | entry_points={
22 | 'console_scripts': [
23 | 'dsc-datatool = dsc_datatool:main',
24 | ],
25 | },
26 | scripts=[
27 | ],
28 | )
29 |
--------------------------------------------------------------------------------
/debian/control:
--------------------------------------------------------------------------------
1 | Source: dsc-datatool
2 | Section: python
3 | Priority: optional
4 | Maintainer: Jerry Lundström
5 | Build-Depends: debhelper (>= 10), python3 (>= 3.5), python3-maxminddb,
6 | python3-yaml, python3-setuptools, dh-python
7 | Standards-Version: 3.9.4
8 | Homepage: https://www.dns-oarc.net/oarc/data/dsc
9 | Vcs-Git: https://codeberg.org/DNS-OARC/dsc-datatool.git
10 | Vcs-Browser: https://codeberg.org/DNS-OARC/dsc-datatool
11 | X-Python3-Version: >= 3.5
12 |
13 | Package: dsc-datatool
14 | Architecture: all
15 | Depends: ${misc:Depends}, ${python3:Depends}
16 | Suggests: dsc
17 | Description: Export DSC data to other formats and/or databases
18 | Tool for converting, exporting, merging and transforming DSC data.
19 |
--------------------------------------------------------------------------------
/.forgejo/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: test
2 | on: pull_request
3 | jobs:
4 | test:
5 | runs-on: docker
6 | steps:
7 | - uses: actions/checkout@v4
8 | - name: Set up Python 3.13
9 | uses: actions/setup-python@v5
10 | - name: Install dependencies
11 | run: |
12 | apt-get update
13 | apt-get install -y python3-maxminddb python3-yaml wget python3-pip
14 | python3 -m pip install --upgrade pip
15 | pip install .
16 | - name: Test
17 | run: |
18 | cd tests
19 | rm ipv4-address-space.csv ipv6-unicast-address-assignments.csv
20 | wget https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.csv
21 | wget https://www.iana.org/assignments/ipv6-unicast-address-assignments/ipv6-unicast-address-assignments.csv
22 | ./test.sh
23 |
--------------------------------------------------------------------------------
/tests/20190719/client_port_range.dat:
--------------------------------------------------------------------------------
1 | 1563520560 58368-59391 8 1024-2047 3 45056-46079 7 31744-32767 5 15360-16383 7 30720-31743 4 9216-10239 3 5120-6143 4 25600-26623 4 41984-43007 9 43008-44031 6 62464-63487 4 22528-23551 4 10240-11263 4 39936-40959 5 34816-35839 7 16384-17407 5 32768-33791 6 37888-38911 7 53248-54271 3 3072-4095 7 47104-48127 5 21504-22527 2 49152-50175 6 6144-7167 2 33792-34815 12 61440-62463 8 51200-52223 2 27648-28671 3 4096-5119 3 46080-47103 7 56320-57343 11 63488-64511 8 50176-51199 4 2048-3071 5 8192-9215 3 57344-58367 3 14336-15359 6 52224-53247 6 55296-56319 10 12288-13311 5 24576-25599 11 60416-61439 1 26624-27647 4 17408-18431 4 7168-8191 4 48128-49151 4 38912-39935 4 23552-24575 4 28672-29695 5 20480-21503 3 40960-41983 7 54272-55295 5 13312-14335 6 11264-12287 4 19456-20479 8 36864-37887 6 29696-30719 4 35840-36863 12 18432-19455 4 44032-45055 3 59392-60415 7
2 | #MD5 21f1a5b2da887ab9b0c608f34992d7de
3 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/tests/20190719/rcode_vs_replylen.dat:
--------------------------------------------------------------------------------
1 | 2 31 6
2 | 0 293 3
3 | 0 112 1
4 | 0 232 31
5 | 0 396 2
6 | 0 89 1
7 | 0 302 1
8 | 0 94 1
9 | 0 298 3
10 | 0 1118 10
11 | 0 85 1
12 | 0 563 6
13 | 0 132 2
14 | 0 245 3
15 | 0 233 7
16 | 0 389 1
17 | 0 174 1
18 | 0 88 4
19 | 0 241 4
20 | 0 253 2
21 | 0 412 1
22 | 0 42 4
23 | 0 104 4
24 | 0 75 40
25 | 0 66 45
26 | 0 54 84
27 | 0 155 1
28 | 0 131 2
29 | 0 151 1
30 | 0 229 1
31 | 0 328 1
32 | 0 362 1
33 | 0 1100 2
34 | 0 98 1
35 | 0 722 4
36 | 0 368 7
37 | 0 111 1
38 | 0 237 1
39 | 0 235 1
40 | 0 1141 1
41 | 0 62 3
42 | 0 99 2
43 | 0 84 2
44 | 0 102 2
45 | 0 345 1
46 | 0 61 2
47 | 0 239 2
48 | 0 261 2
49 | 0 259 1
50 | 0 309 5
51 | 0 244 17
52 | 0 80 1
53 | 0 69 1
54 | 0 1472 6
55 | 0 587 3
56 | 0 77 1
57 | 0 125 1
58 | 0 127 1
59 | 0 110 2
60 | 0 324 1
61 | 0 591 1
62 | 0 96 2
63 | 0 271 9
64 | 0 50 2
65 | 0 296 8
66 | 0 202 1
67 | 0 299 1
68 | 0 268 6
69 | 0 1146 1
70 | 0 272 11
71 | 0 41 2
72 | 0 57 1
73 | 0 123 2
74 | 0 49 7
75 | 0 294 1
76 | 0 478 3
77 | 0 326 1
78 | 0 82 5
79 | 0 379 4
80 | 0 64 1
81 | 0 87 2
82 | 0 574 2
83 | 3 130 1
84 | 3 101 2
85 | 3 92 2
86 | 3 795 1
87 | 3 694 2
88 | #MD5 f7092a6510cfbece8835bc3b41f8e20d
89 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DSC DataTool
2 |
3 | [](https://sonarcloud.io/summary/new_code?id=dns-oarc%3Adsc-datatool) [](https://sonarcloud.io/summary/new_code?id=dns-oarc%3Adsc-datatool)
4 |
5 | Tool for converting, exporting, merging and transforming DSC data.
6 |
7 | Please have a look at the man-page(s) `dsc-datatool` (1) on how to use or
8 | [the wiki article](https://codeberg.org/DNS-OARC/dsc-datatool/wiki/Setting-up-a-test-Grafana)
9 | on how to set this up using Influx DB and Grafana.
10 |
11 | More information about DSC may be found here:
12 | - https://www.dns-oarc.net/tools/dsc
13 | - https://www.dns-oarc.net/oarc/data/dsc
14 |
15 | Issues should be reported here:
16 | - https://codeberg.org/DNS-OARC/dsc-datatool/issues
17 |
18 | General support and discussion:
19 | - Mattermost: https://chat.dns-oarc.net/community/channels/oarc-software
20 |
21 | ## Dependencies
22 |
23 | `dsc-datatool` requires the following Python libraries:
24 | - PyYAML
25 | - maxminddb
26 |
27 | ## Python Development Environment
28 |
29 | Using Ubuntu/Debian:
30 |
31 | ```
32 | sudo apt-get install python3-maxminddb python3-yaml python3-venv
33 | python3 -m venv venv --system-site-packages
34 | . venv/bin/activate
35 | pip install -e . --no-deps
36 | ```
37 |
--------------------------------------------------------------------------------
/man/man7/dsc-datatool-output-influxdb.7:
--------------------------------------------------------------------------------
1 | .TH "dsc-datatool-output influxdb" "7"
2 | .SH NAME
3 | InfluxDB \- InfluxDB output.
4 | .SH SYNOPSIS
5 | .SY dsc-datatool
6 | .B \-\-output
7 | .I """;InfluxDB;"""
8 | .YS
9 | .SH DESCRIPTION
10 | This output generates InfluxDB importable output to stdout or to a specified
11 | file.
12 | .SH OPTIONS
13 | .TP
14 | .BR timestamp =[start|stop]
15 | Choose which timestamp from the dataset to use in the InfluxDB output to
16 | specify when the metrics took place.
17 |
18 | Default to
19 | .I start
20 | timestamp.
21 | .TP
22 | .BR file =
23 | Specify a file to output to instead of stdout.
24 | .TP
25 | .BR append
26 | If given, the output will be appended to the file specified rather then
27 | overwritten.
28 | .TP
29 | .BR dml
30 | Add a
31 | .I "# DML"
32 | header to the output.
33 | .TP
34 | .BR database =name
35 | If
36 | .I dml
37 | is used, this can be used to specify which database the output should be
38 | imported into.
39 | .LP
40 | .SH "SEE ALSO"
41 | .BR dsc-datatool (1),
42 | .BR influx (1)
43 | .SH AUTHORS
44 | Jerry Lundström, DNS-OARC
45 | .LP
46 | Maintained by DNS-OARC
47 | .LP
48 | .RS
49 | .I https://www.dns-oarc.net/tools/dsc
50 | .RE
51 | .LP
52 | .SH BUGS
53 | For issues and feature requests please use:
54 | .LP
55 | .RS
56 | \fIhttps://codeberg.org/DNS-OARC/dsc-datatool/issues\fP
57 | .RE
58 | .LP
59 | For question and help please use:
60 | .LP
61 | .RS
62 | \fIhttps://chat.dns-oarc.net/community/channels/oarc-software\fP
63 | .RE
64 | .LP
65 |
--------------------------------------------------------------------------------
/man/man7/dsc-datatool-transformer-labler.7:
--------------------------------------------------------------------------------
1 | .TH "dsc-datatool-transformer labler" "7"
2 | .SH NAME
3 | Labler \- Rewrite numeric labels to textual labels using the provided YAML data as lookup tables.
4 | .SH SYNOPSIS
5 | .SY dsc-datatool
6 | .B \-\-transform
7 | .I """;Labler;;yaml="""
8 | .YS
9 | .SH DESCRIPTION
10 | This transformer rewrites labels in datasets based on information provided
11 | in a YAML file.
12 |
13 | The YAML structure is as follows:
14 | .EX
15 | ---
16 | dataset_name:
17 | DimentionName:
18 | DimentionValue: RewriteTo
19 | .EE
20 |
21 | The
22 | .I dataset_name
23 | is the name of the dataset,
24 | .I DimentionName
25 | is the name of the dimension to rewrite and
26 | .I DimensionValue
27 | is the value to change to
28 | .IR RewriteTo .
29 | .SH OPTIONS
30 | .TP
31 | .B dataset
32 | See
33 | .IR dsc-datatool (1)
34 | on how to specify which dataset(s) to run the transformer on.
35 | .TP
36 | .BR yaml =
37 | The YAML file to load rewrite data from (required).
38 | .LP
39 | .SH "SEE ALSO"
40 | .BR dsc-datatool (1)
41 | .SH AUTHORS
42 | Jerry Lundström, DNS-OARC
43 | .LP
44 | Maintained by DNS-OARC
45 | .LP
46 | .RS
47 | .I https://www.dns-oarc.net/tools/dsc
48 | .RE
49 | .LP
50 | .SH BUGS
51 | For issues and feature requests please use:
52 | .LP
53 | .RS
54 | \fIhttps://codeberg.org/DNS-OARC/dsc-datatool/issues\fP
55 | .RE
56 | .LP
57 | For question and help please use:
58 | .LP
59 | .RS
60 | \fIhttps://chat.dns-oarc.net/community/channels/oarc-software\fP
61 | .RE
62 | .LP
63 |
--------------------------------------------------------------------------------
/contrib/iana-dns-params-toyaml.py:
--------------------------------------------------------------------------------
1 | import yaml
2 | import csv
3 | from urllib.request import Request, urlopen
4 | from io import StringIO
5 |
6 | rcode = {}
7 | qtype = {}
8 | opcode = {}
9 |
10 | for row in csv.reader(StringIO(urlopen(Request('http://www.iana.org/assignments/dns-parameters/dns-parameters-6.csv')).read().decode('utf-8'))):
11 | if row[0] == 'RCODE':
12 | continue
13 | rcode[row[0]] = row[1]
14 |
15 | for row in csv.reader(StringIO(urlopen(Request('http://www.iana.org/assignments/dns-parameters/dns-parameters-4.csv')).read().decode('utf-8'))):
16 | if row[0] == 'TYPE':
17 | continue
18 | qtype[row[1]] = row[0]
19 |
20 | for row in csv.reader(StringIO(urlopen(Request('http://www.iana.org/assignments/dns-parameters/dns-parameters-5.csv')).read().decode('utf-8'))):
21 | if row[0] == 'OpCode':
22 | continue
23 | opcode[row[0]] = row[1]
24 |
25 | y = {}
26 |
27 | for n in ['rcode', 'client_addr_vs_rcode', 'rcode_vs_replylen']:
28 | y[n] = { 'Rcode': {} }
29 | for k, v in rcode.items():
30 | y[n]['Rcode'][k] = v
31 |
32 | for n in ['qtype', 'transport_vs_qtype', 'certain_qnames_vs_qtype', 'qtype_vs_tld', 'qtype_vs_qnamelen', 'chaos_types_and_names', 'dns_ip_version_vs_qtype']:
33 | y[n] = { 'Qtype': {} }
34 | for k, v in qtype.items():
35 | if v == '*':
36 | v = 'wildcard'
37 | y[n]['Qtype'][k] = v
38 |
39 | for n in ['opcode']:
40 | y[n] = { 'Opcode': {} }
41 | for k, v in rcode.items():
42 | y[n]['Opcode'][k] = v
43 |
44 | print(yaml.dump(y, explicit_start=True, default_flow_style=False))
45 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | DSC DataTool
2 |
3 | Copyright (c) 2016-2024 OARC, Inc.
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions
8 | are met:
9 |
10 | 1. Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 |
13 | 2. Redistributions in binary form must reproduce the above copyright
14 | notice, this list of conditions and the following disclaimer in
15 | the documentation and/or other materials provided with the
16 | distribution.
17 |
18 | 3. Neither the name of the copyright holder nor the names of its
19 | contributors may be used to endorse or promote products derived
20 | from this software without specific prior written permission.
21 |
22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 | POSSIBILITY OF SUCH DAMAGE.
34 |
--------------------------------------------------------------------------------
/man/man7/dsc-datatool-transformer-netremap.7:
--------------------------------------------------------------------------------
1 | .TH "dsc-datatool-transformer netremap" "7"
2 | .SH NAME
3 | NetRemap \- Remap network addresses to other ranges/subnets.
4 | .SH SYNOPSIS
5 | .SY dsc-datatool
6 | .B \-\-transform
7 | .I """;NetRemap;;"""
8 | .YS
9 | .SH DESCRIPTION
10 | This transformer can remap network ranges on IP addresses and subnets.
11 | .SH OPTIONS
12 | .TP
13 | .B dataset
14 | See
15 | .IR dsc-datatool (1)
16 | on how to specify which dataset(s) to run the transformer on.
17 | .TP
18 | .BR net =
19 | The network to remap both IPv4 and IPv6 addresses and networks, specify
20 | only the number in a short-form network (e.g. "/").
21 | .TP
22 | .BR v4net =
23 | The IPv4 network to use for IPv4 addresses and networks, default to
24 | .I net
25 | if that is specified.
26 | .TP
27 | .BR v6net =
28 | The IPv6 network to use for IPv6 addresses and networks, default to
29 | .I net
30 | if that is specified.
31 | .TP
32 | .BR nonstrict =
33 | If set (to any value) then a non-strict mode is enabled which will disregard
34 | any bad data in the dataset, skipping it completely.
35 | Default is strict mode.
36 | .LP
37 | .SH "SEE ALSO"
38 | .BR dsc-datatool (1)
39 | .SH AUTHORS
40 | Jerry Lundström, DNS-OARC
41 | .LP
42 | Maintained by DNS-OARC
43 | .LP
44 | .RS
45 | .I https://www.dns-oarc.net/tools/dsc
46 | .RE
47 | .LP
48 | .SH BUGS
49 | For issues and feature requests please use:
50 | .LP
51 | .RS
52 | \fIhttps://codeberg.org/DNS-OARC/dsc-datatool/issues\fP
53 | .RE
54 | .LP
55 | For question and help please use:
56 | .LP
57 | .RS
58 | \fIhttps://chat.dns-oarc.net/community/channels/oarc-software\fP
59 | .RE
60 | .LP
61 |
--------------------------------------------------------------------------------
/dsc_datatool/transformer/labler.py:
--------------------------------------------------------------------------------
1 | """dsc_datatool.transformer.labler
2 |
3 | See `man dsc-datatool-transformer labler`.
4 |
5 | Part of dsc_datatool.
6 |
7 | :copyright: 2024 OARC, Inc.
8 | """
9 |
10 | import yaml
11 |
12 | from dsc_datatool import Transformer, encoding
13 |
14 |
15 | def _process(label, d):
16 | l = label.get(d.name, None)
17 | if d.values:
18 | if l is None:
19 | return
20 |
21 | values = d.values
22 | d.values = {}
23 |
24 | for k, v in values.items():
25 | nk = l.get(k, None)
26 | d.values[nk or k] = v
27 |
28 | return
29 |
30 | if l:
31 | v = l.get(d.value, None)
32 | if v:
33 | d.value = v
34 | for d2 in d.dimensions:
35 | _process(label, d2)
36 |
37 |
38 | class Labler(Transformer):
39 | label = None
40 |
41 |
42 | def __init__(self, opts):
43 | Transformer.__init__(self, opts)
44 | if not 'yaml' in opts:
45 | raise Exception('yaml=file option required')
46 | f = open(opts.get('yaml'), 'r', encoding=encoding)
47 | self.label = yaml.safe_load(f)
48 | f.close()
49 |
50 |
51 | def process(self, datasets):
52 | if self.label is None:
53 | return
54 |
55 | for dataset in datasets:
56 | label = self.label.get(dataset.name, None)
57 | if label is None:
58 | continue
59 |
60 | for d in dataset.dimensions:
61 | _process(label, d)
62 |
63 |
64 | import sys
65 | if sys.version_info[0] == 3 and sys.version_info[1] == 5: # pragma: no cover
66 | Transformer.__init_subclass__(Labler)
67 |
--------------------------------------------------------------------------------
/tests/test_objects.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from dsc_datatool import Dataset, Dimension, Input, Output, Generator, Transformer
3 |
4 |
5 | def test_dataset():
6 | o = Dataset()
7 | assert '%r' % o == ''
8 |
9 |
10 | def test_dimension():
11 | o = Dimension('test')
12 | assert '%r' % o == ''
13 |
14 |
15 | def test_input():
16 | o = Input()
17 | with pytest.raises(Exception):
18 | o.process("test")
19 |
20 | class Input1(Input):
21 | def process(self, file):
22 | pass
23 | with pytest.raises(Exception):
24 | class Input1(Input):
25 | def process(self, file):
26 | pass
27 |
28 |
29 | def test_output():
30 | o = Output({})
31 | with pytest.raises(Exception):
32 | o.process([])
33 |
34 | class Output1(Output):
35 | def process(self, file):
36 | pass
37 | with pytest.raises(Exception):
38 | class Output1(Output):
39 | def process(self, file):
40 | pass
41 |
42 |
43 | def test_generator():
44 | o = Generator({})
45 | with pytest.raises(Exception):
46 | o.process([])
47 |
48 | class Generator1(Generator):
49 | def process(self, file):
50 | pass
51 | with pytest.raises(Exception):
52 | class Generator1(Generator):
53 | def process(self, file):
54 | pass
55 |
56 |
57 | def test_transformer():
58 | o = Transformer({})
59 | with pytest.raises(Exception):
60 | o.process([])
61 |
62 | class Transformer1(Transformer):
63 | def process(self, file):
64 | pass
65 | with pytest.raises(Exception):
66 | class Transformer1(Transformer):
67 | def process(self, file):
68 | pass
69 |
--------------------------------------------------------------------------------
/man/man7/dsc-datatool-generator-client_subnet_country.7:
--------------------------------------------------------------------------------
1 | .TH "dsc-datatool-generator client_subnet_country" "7"
2 | .SH NAME
3 | client_subnet_country \- Generates country information based on client subnet using Maxmind database.
4 | .SH SYNOPSIS
5 | .SY dsc-datatool
6 | .B \-\-generator
7 | .I """;client_subnet_country;"""
8 | .YS
9 | .SH DESCRIPTION
10 | This generator looks up country code in a Maxmind database for the subnets
11 | in the
12 | .I client_subnet
13 | dataset and the dataset
14 | .I client_subnet_country
15 | from that.
16 | .SH OPTIONS
17 | .TP
18 | .BR path =
19 | Search for the Maxmind database in the specified
20 | .IR directory .
21 | This option can be given multiple times to search in multiple directories.
22 |
23 | Default search paths are:
24 | .IR /var/lib/GeoIP ,
25 | .IR /usr/share/GeoIP ,
26 | .IR /usr/local/share/GeoIP .
27 | .TP
28 | .BR filename =filename
29 | The database filename to search for, default to
30 | .IR GeoLite2-Country.mmdb .
31 | .TP
32 | .BR db =/path/to/database.mmdb
33 | Full path to Maxmind database, this option overrides
34 | .I path
35 | and
36 | .IR filename .
37 | .TP
38 | .BR nonstrict =
39 | If set (to any value) then a non-strict mode is enabled which will disregard
40 | any bad data in the dataset, skipping it completely.
41 | Default is strict mode.
42 | .LP
43 | .SH "SEE ALSO"
44 | .BR dsc-datatool (1),
45 | .BR geoipupdate (1)
46 | .SH AUTHORS
47 | Jerry Lundström, DNS-OARC
48 | .LP
49 | Maintained by DNS-OARC
50 | .LP
51 | .RS
52 | .I https://www.dns-oarc.net/tools/dsc
53 | .RE
54 | .LP
55 | .SH BUGS
56 | For issues and feature requests please use:
57 | .LP
58 | .RS
59 | \fIhttps://codeberg.org/DNS-OARC/dsc-datatool/issues\fP
60 | .RE
61 | .LP
62 | For question and help please use:
63 | .LP
64 | .RS
65 | \fIhttps://chat.dns-oarc.net/community/channels/oarc-software\fP
66 | .RE
67 | .LP
68 |
--------------------------------------------------------------------------------
/man/man7/dsc-datatool-transformer-reranger.7:
--------------------------------------------------------------------------------
1 | .TH "dsc-datatool-transformer reranger" "7"
2 | .SH NAME
3 | ReRanger \- Rewrite ranged or numerical statistics into other ranges.
4 | .SH SYNOPSIS
5 | .SY dsc-datatool
6 | .B \-\-transform
7 | .I """;ReRanger;;"""
8 | .YS
9 | .SH DESCRIPTION
10 | This transformer can re-range values in datasets to new rangers.
11 |
12 | It supports both values that are a single numerical value or one that is
13 | already a range itself
14 | .RI ( num\-num ).
15 | .SH OPTIONS
16 | .TP
17 | .B dataset
18 | See
19 | .IR dsc-datatool (1)
20 | on how to specify which dataset(s) to run the transformer on.
21 | .TP
22 | .BR key =[low|mid|high]
23 | Specify what value to use when re-ranging an already ranged value
24 | .RI (low\-high).
25 |
26 | Default to
27 | .IR mid ,
28 | which is high minus low then divided by 2.
29 | .TP
30 | .BR func =
31 | The function to use when aggregating multiple values into a new ranger,
32 | default to
33 | .IR sum .
34 |
35 | Currently only one function exists,
36 | .IR sum ,
37 | which adds the sum of all values into the new range.
38 | .TP
39 | .B allow_invalid_keys
40 | If given the "invalid" keys/values that is not numerical or a range will be
41 | passed through unmodified.
42 | .TP
43 | .BR range =
44 | The new range given as
45 | .I /number
46 | (required).
47 |
48 | For example
49 | .I range=/64
50 | will re-range all values into buckets of 64, 0-63, 64-127 and so on.
51 | .LP
52 | .SH "SEE ALSO"
53 | .BR dsc-datatool (1)
54 | .SH AUTHORS
55 | Jerry Lundström, DNS-OARC
56 | .LP
57 | Maintained by DNS-OARC
58 | .LP
59 | .RS
60 | .I https://www.dns-oarc.net/tools/dsc
61 | .RE
62 | .LP
63 | .SH BUGS
64 | For issues and feature requests please use:
65 | .LP
66 | .RS
67 | \fIhttps://codeberg.org/DNS-OARC/dsc-datatool/issues\fP
68 | .RE
69 | .LP
70 | For question and help please use:
71 | .LP
72 | .RS
73 | \fIhttps://chat.dns-oarc.net/community/channels/oarc-software\fP
74 | .RE
75 | .LP
76 |
--------------------------------------------------------------------------------
/debian/copyright:
--------------------------------------------------------------------------------
1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2 | Upstream-Name: dsc-datatool
3 | Source: https://codeberg.org/DNS-OARC/dsc-datatool
4 |
5 | Files: *
6 | Copyright: 2016-2024 OARC, Inc.
7 | License: BSD-3-Clause
8 |
9 | Files: debian/*
10 | Copyright: 2024 Jerry Lundström
11 | License: BSD-3-Clause
12 |
13 | License: BSD-3-Clause
14 | Redistribution and use in source and binary forms, with or without
15 | modification, are permitted provided that the following conditions
16 | are met:
17 | .
18 | 1. Redistributions of source code must retain the above copyright
19 | notice, this list of conditions and the following disclaimer.
20 | .
21 | 2. Redistributions in binary form must reproduce the above copyright
22 | notice, this list of conditions and the following disclaimer in
23 | the documentation and/or other materials provided with the
24 | distribution.
25 | .
26 | 3. Neither the name of the copyright holder nor the names of its
27 | contributors may be used to endorse or promote products derived
28 | from this software without specific prior written permission.
29 | .
30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 | POSSIBILITY OF SUCH DAMAGE.
42 |
--------------------------------------------------------------------------------
/man/man7/dsc-datatool-generator-client_subnet_authority.7:
--------------------------------------------------------------------------------
1 | .TH "dsc-datatool-generator client_subnet_authority" "7"
2 | .SH NAME
3 | client_subnet_authority \- Generates network authority information (RIR) based on client subnet.
4 | .SH SYNOPSIS
5 | .SY dsc-datatool
6 | .B \-\-generator
7 | .I """;client_subnet_authority;"""
8 | .YS
9 | .SH DESCRIPTION
10 | This generator will lookup the network authority (RIR) based network
11 | information in the
12 | .I client_subnet
13 | dataset and generate a new dataset
14 | .IR client_subnet_authority .
15 |
16 | The network authority lookup will be done from imports of CSV files or by
17 | fetching the required data from IANA.
18 | .SH OPTIONS
19 | .TP
20 | .BR csv =
21 | Read the network authority information from the given
22 | .IR file(s) .
23 | This option can be a single file, a list of comma separated files or given
24 | multiple times.
25 | .TP
26 | .BR fetch =yes
27 | Fetch the network authority information from IANA IP address space registry
28 | for IPv4 and IPv6.
29 | .TP
30 | .BR urlv4 =url
31 | URL for IANA IPv4 address space registry, default to
32 | .IR https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.csv .
33 | .TP
34 | .BR urlv6 =url
35 | URL for IANA IPv6 address space registry, default to
36 | .IR https://www.iana.org/assignments/ipv6-unicast-address-assignments/ipv6-unicast-address-assignments.csv .
37 | .TP
38 | .BR nonstrict =
39 | If set (to any value) then a non-strict mode is enabled which will disregard
40 | any bad data in the dataset, skipping it completely.
41 | Default is strict mode.
42 | .LP
43 | .SH "SEE ALSO"
44 | .BR dsc-datatool (1)
45 | .SH AUTHORS
46 | Jerry Lundström, DNS-OARC
47 | .LP
48 | Maintained by DNS-OARC
49 | .LP
50 | .RS
51 | .I https://www.dns-oarc.net/tools/dsc
52 | .RE
53 | .LP
54 | .SH BUGS
55 | For issues and feature requests please use:
56 | .LP
57 | .RS
58 | \fIhttps://codeberg.org/DNS-OARC/dsc-datatool/issues\fP
59 | .RE
60 | .LP
61 | For question and help please use:
62 | .LP
63 | .RS
64 | \fIhttps://chat.dns-oarc.net/community/channels/oarc-software\fP
65 | .RE
66 | .LP
67 |
--------------------------------------------------------------------------------
/dsc_datatool/transformer/net_remap.py:
--------------------------------------------------------------------------------
1 | """dsc_datatool.transformer.net_remap
2 |
3 | See `man dsc-datatool-transformer netremap`.
4 |
5 | Part of dsc_datatool.
6 |
7 | :copyright: 2024 OARC, Inc.
8 | """
9 |
10 | import ipaddress
11 |
12 | from dsc_datatool import Transformer, args
13 |
14 |
15 | class NetRemap(Transformer):
16 | v4net = None
17 | v6net = None
18 | nonstrict = False
19 |
20 |
21 | def __init__(self, opts):
22 | Transformer.__init__(self, opts)
23 | net = opts.get('net', None)
24 | self.v4net = opts.get('v4net', net)
25 | self.v6net = opts.get('v6net', net)
26 |
27 | if not self.v4net:
28 | raise Exception('v4net (or net) must be given')
29 | if not self.v6net:
30 | raise Exception('v6net (or net) must be given')
31 |
32 | if opts.get('nonstrict', False):
33 | self.nonstrict = True
34 |
35 |
36 | def _process(self, dimension):
37 | if not dimension.values:
38 | for d2 in dimension.dimensions:
39 | self._process(d2)
40 | return
41 |
42 | values = dimension.values
43 | dimension.values = {}
44 |
45 | for k, v in values.items():
46 | if k == args.skipped_key:
47 | continue
48 | elif k == args.skipped_sum_key:
49 | dimension.values['0'] = v
50 | continue
51 |
52 | try:
53 | ip = ipaddress.ip_address(k)
54 | except Exception as e:
55 | if not self.nonstrict:
56 | raise e
57 | continue
58 | if ip.version == 4:
59 | nkey = str(ipaddress.IPv4Network('%s/%s' % (ip, self.v4net), strict=False).network_address)
60 | else:
61 | nkey = str(ipaddress.IPv6Network('%s/%s' % (ip, self.v6net), strict=False).network_address)
62 |
63 | if not nkey in dimension.values:
64 | dimension.values[nkey] = v
65 | else:
66 | dimension.values[nkey] += v
67 |
68 |
69 | def process(self, datasets):
70 | for dataset in datasets:
71 | for dimension in dataset.dimensions:
72 | self._process(dimension)
73 |
74 |
75 | import sys
76 | if sys.version_info[0] == 3 and sys.version_info[1] == 5: # pragma: no cover
77 | Transformer.__init_subclass__(NetRemap)
78 |
--------------------------------------------------------------------------------
/man/man7/dsc-datatool-output-prometheus.7:
--------------------------------------------------------------------------------
1 | .TH "dsc-datatool-output prometheus" "7"
2 | .SH NAME
3 | Prometheus \- Prometheus output.
4 | .SH SYNOPSIS
5 | .SY dsc-datatool
6 | .B \-\-output
7 | .I """;Prometheus;"""
8 | .YS
9 | .SH DESCRIPTION
10 | This output generates Prometheus importable output to stdout or to a specified
11 | file.
12 | .SS Prometheus' node_exporter
13 | This output can be used together with Prometheus'
14 | .IR node_exporter 's
15 | Textfile Collector to automate statistics gathering but some specific
16 | setup and requirements must be meet.
17 |
18 | You must hide the timestamp with option
19 | .B timestamp=hide
20 | because timestamps are not supported by the Textfile Collector.
21 |
22 | You must make sure only one XML file from a server+node combination is
23 | processed at a time.
24 | Because otherwise you will get multiple data point for the same metric
25 | and this will generate errors from the Textfile Collector, since it does
26 | not support timestamps and cannot separate the measurements.
27 |
28 | You must make sure that only one file (per server+node combo) is generated
29 | for the Textfile Collector to read, and it should be the same between runs.
30 | See Textfile Collectors documentation how to setup that atomically.
31 | .SH OPTIONS
32 | .TP
33 | .BR timestamp =[hide|start|stop]
34 | Choose which timestamp from the dataset to use in the Prometheus output to
35 | specify when the metrics took place.
36 |
37 | Default to
38 | .I start
39 | timestamp.
40 | .TP
41 | .BR file =
42 | Specify a file to output to instead of stdout.
43 | .TP
44 | .BR append
45 | If given, the output will be appended to the file specified rather then
46 | overwritten.
47 | .TP
48 | .BR prefix =
49 | Use the given string as prefix on all metric names.
50 | .LP
51 | .SH "SEE ALSO"
52 | .BR dsc-datatool (1)
53 |
54 | .I https://prometheus.io/docs/guides/node-exporter/
55 |
56 | .I https://github.com/prometheus/node_exporter#textfile-collector
57 | .SH AUTHORS
58 | Jerry Lundström, DNS-OARC
59 | .LP
60 | Maintained by DNS-OARC
61 | .LP
62 | .RS
63 | .I https://www.dns-oarc.net/tools/dsc
64 | .RE
65 | .LP
66 | .SH BUGS
67 | For issues and feature requests please use:
68 | .LP
69 | .RS
70 | \fIhttps://codeberg.org/DNS-OARC/dsc-datatool/issues\fP
71 | .RE
72 | .LP
73 | For question and help please use:
74 | .LP
75 | .RS
76 | \fIhttps://chat.dns-oarc.net/community/channels/oarc-software\fP
77 | .RE
78 | .LP
79 |
--------------------------------------------------------------------------------
/dsc_datatool/input/xml.py:
--------------------------------------------------------------------------------
1 | """dsc_datatool.input.xml
2 |
3 | Input plugin to generate `Dataset`'s from DSC XML files.
4 |
5 | Part of dsc_datatool.
6 |
7 | :copyright: 2024 OARC, Inc.
8 | """
9 |
10 | import logging
11 | from xml.dom import minidom
12 | import base64
13 |
14 | from dsc_datatool import Input, Dataset, Dimension, process_dataset
15 |
16 |
17 | class XML(Input):
18 | def process(self, file):
19 | dom = minidom.parse(file)
20 | datasets = []
21 | for array in dom.getElementsByTagName('array'):
22 | if process_dataset and not array.getAttribute('name') in process_dataset:
23 | continue
24 |
25 | dataset = Dataset()
26 | dataset.name = array.getAttribute('name')
27 | dataset.start_time = int(array.getAttribute('start_time'))
28 | dataset.stop_time = int(array.getAttribute('stop_time'))
29 |
30 | dimensions = [None, None]
31 | for dimension in array.getElementsByTagName('dimension'):
32 | if dimension.getAttribute('number') == '1':
33 | if dimensions[0]:
34 | logging.warning('Overwriting dimension 1 for %s' % dataset.name)
35 | dimensions[0] = dimension.getAttribute('type')
36 | elif dimension.getAttribute('number') == '2':
37 | if dimensions[1]:
38 | logging.warning('Overwriting dimension 2 for %s' % dataset.name)
39 | dimensions[1] = dimension.getAttribute('type')
40 | else:
41 | logging.warning('Invalid dimension number %r for %s' % (dimension.getAttribute('number'), dataset.name))
42 |
43 | for node1 in array.getElementsByTagName(dimensions[0]):
44 | d1 = Dimension(dimensions[0])
45 | d1.value = node1.getAttribute('val')
46 | try:
47 | if node1.getAttribute('base64'):
48 | d1.value = base64.b64decode(d1.value).decode('utf-8')
49 | except Exception as e:
50 | pass
51 | dataset.dimensions.append(d1)
52 |
53 | d2 = Dimension(dimensions[1])
54 | d1.dimensions.append(d2)
55 | for node2 in node1.getElementsByTagName(dimensions[1]):
56 | val = node2.getAttribute('val')
57 | try:
58 | if node2.getAttribute('base64'):
59 | val = base64.b64decode(val).decode('utf-8')
60 | except Exception as e:
61 | pass
62 | d2.values[val] = int(node2.getAttribute('count'))
63 |
64 | datasets.append(dataset)
65 |
66 | return datasets
67 |
68 |
69 | import sys
70 | if sys.version_info[0] == 3 and sys.version_info[1] == 5: # pragma: no cover
71 | Input.__init_subclass__(XML)
72 |
--------------------------------------------------------------------------------
/dsc_datatool/output/influxdb.py:
--------------------------------------------------------------------------------
1 | """dsc_datatool.output.influxdb
2 |
3 | See `man dsc-datatool-output influxdb`.
4 |
5 | Part of dsc_datatool.
6 |
7 | :copyright: 2024 OARC, Inc.
8 | """
9 |
10 | import re
11 | import sys
12 | import atexit
13 |
14 | from dsc_datatool import Output, args, encoding
15 |
16 |
17 | _re = re.compile(r'([,=\\\s])')
18 |
19 |
20 | def _key(key):
21 | return re.sub(_re, r'\\\1', key)
22 |
23 |
24 | def _val(val):
25 | ret = re.sub(_re, r'\\\1', val)
26 | if ret == '':
27 | return '""'
28 | return ret
29 |
30 |
31 | def _process(tags, timestamp, dimension, fh):
32 | if dimension.dimensions is None:
33 | return
34 |
35 | if len(dimension.dimensions) > 0:
36 | if not (dimension.name == 'All' and dimension.value == 'ALL'):
37 | tags += ',%s=%s' % (_key(dimension.name.lower()), _val(dimension.value))
38 | for d2 in dimension.dimensions:
39 | _process(tags, timestamp, d2, fh)
40 | return
41 |
42 | if dimension.values is None:
43 | return
44 |
45 | if len(dimension.values) > 0:
46 | tags += ',%s=' % _key(dimension.name.lower())
47 |
48 | for k, v in dimension.values.items():
49 | print('%s%s value=%s %s' % (tags, _val(k), v, timestamp), file=fh)
50 |
51 |
52 | class InfluxDB(Output):
53 | start_timestamp = True
54 | fh = None
55 |
56 |
57 | def __init__(self, opts):
58 | Output.__init__(self, opts)
59 | timestamp = opts.get('timestamp', 'start')
60 | if timestamp == 'start':
61 | pass
62 | elif timestamp == 'stop':
63 | self.start_timestamp = False
64 | else:
65 | raise Exception('timestamp option invalid')
66 | file = opts.get('file', None)
67 | append = opts.get('append', False)
68 | if file:
69 | if append:
70 | self.fh = open(file, 'a', encoding=encoding)
71 | else:
72 | self.fh = open(file, 'w', encoding=encoding)
73 | atexit.register(self.close)
74 | else:
75 | self.fh = sys.stdout
76 |
77 | if opts.get('dml', False):
78 | print('# DML', file=self.fh)
79 | database = opts.get('database', None)
80 | if database:
81 | print('# CONTEXT-DATABASE: %s' % database, file=self.fh)
82 |
83 |
84 | def close(self):
85 | if self.fh:
86 | self.fh.close()
87 | self.fh = None
88 |
89 |
90 | def process(self, datasets):
91 | for dataset in datasets:
92 | tags = '%s,server=%s,node=%s' % (_key(dataset.name.lower()), args.server, args.node)
93 | if self.start_timestamp:
94 | timestamp = dataset.start_time * 1000000000
95 | else:
96 | timestamp = dataset.end_time * 1000000000
97 |
98 | for d in dataset.dimensions:
99 | _process(tags, timestamp, d, self.fh)
100 |
101 |
102 | if sys.version_info[0] == 3 and sys.version_info[1] == 5: # pragma: no cover
103 | Output.__init_subclass__(InfluxDB)
104 |
--------------------------------------------------------------------------------
/dsc_datatool/generator/client_subnet_country.py:
--------------------------------------------------------------------------------
1 | """dsc_datatool.generator.client_subnet_country
2 |
3 | See `man dsc-datatool-generator client_subnet_country`.
4 |
5 | Part of dsc_datatool.
6 |
7 | :copyright: 2024 OARC, Inc.
8 | """
9 |
10 | import maxminddb
11 | import os
12 | import logging
13 |
14 | from dsc_datatool import Generator, Dataset, Dimension, args
15 |
16 |
17 | class client_subnet_country(Generator):
18 | reader = None
19 | nonstrict = False
20 |
21 |
22 | def __init__(self, opts):
23 | Generator.__init__(self, opts)
24 | paths = opts.get('path', ['/var/lib/GeoIP', '/usr/share/GeoIP', '/usr/local/share/GeoIP'])
25 | if not isinstance(paths, list):
26 | paths = [ paths ]
27 | filename = opts.get('filename', 'GeoLite2-Country.mmdb')
28 | db = opts.get('db', None)
29 |
30 | if db is None:
31 | for path in paths:
32 | db = '%s/%s' % (path, filename)
33 | if os.path.isfile(db) and os.access(db, os.R_OK):
34 | break
35 | db = None
36 | if db is None:
37 | raise Exception('Please specify valid Maxmind database with path=,filename= or db=')
38 |
39 | logging.info('Using %s' % db)
40 | self.reader = maxminddb.open_database(db)
41 |
42 | if opts.get('nonstrict', False):
43 | self.nonstrict = True
44 |
45 |
46 | def process(self, datasets):
47 | gen_datasets = []
48 |
49 | for dataset in datasets:
50 | if dataset.name != 'client_subnet':
51 | continue
52 |
53 | subnets = {}
54 | for d1 in dataset.dimensions:
55 | for d2 in d1.dimensions:
56 | for k, v in d2.values.items():
57 | if k == args.skipped_key:
58 | continue
59 | elif k == args.skipped_sum_key:
60 | continue
61 |
62 | if k in subnets:
63 | subnets[k] += v
64 | else:
65 | subnets[k] = v
66 |
67 | cc = {}
68 | for subnet in subnets:
69 | try:
70 | c = self.reader.get(subnet)
71 | except Exception as e:
72 | if not self.nonstrict:
73 | raise e
74 | continue
75 | if c:
76 | iso_code = c.get('country', {}).get('iso_code', '??')
77 | if iso_code in cc:
78 | cc[iso_code] += subnets[subnet]
79 | else:
80 | cc[iso_code] = subnets[subnet]
81 |
82 | if cc:
83 | ccd = Dataset()
84 | ccd.name = 'client_subnet_country'
85 | ccd.start_time = dataset.start_time
86 | ccd.stop_time = dataset.stop_time
87 | gen_datasets.append(ccd)
88 |
89 | ccd1 = Dimension('ClientCountry')
90 | ccd1.values = cc
91 | ccd.dimensions.append(ccd1)
92 |
93 | return gen_datasets
94 |
95 |
96 | import sys
97 | if sys.version_info[0] == 3 and sys.version_info[1] == 5: # pragma: no cover
98 | Generator.__init_subclass__(client_subnet_country)
99 |
--------------------------------------------------------------------------------
/tests/coverage.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -xe
4 |
5 | base=`dirname $0`
6 |
7 | export PATH="$base:$PATH"
8 |
9 | "$base/test.sh"
10 |
11 | dsc-datatool \
12 | -vvv \
13 | -s test-server \
14 | -n test-node \
15 | --output ";InfluxDB;dml=1;database=dsc" \
16 | --transform ";Labler;*;yaml=$base/labler.yaml" \
17 | --transform ";ReRanger;rcode_vs_replylen;range=/64;pad_to=5" \
18 | --transform ";ReRanger;qtype_vs_qnamelen;range=/16;pad_to=3" \
19 | --transform ";ReRanger;client_port_range;key=low;range=/2048;pad_to=5" \
20 | --transform ";ReRanger;edns_bufsiz,priming_queries;key=low;range=/512;pad_to=5;allow_invalid_keys=1" \
21 | --transform ";ReRanger;priming_responses;key=low;range=/128;pad_to=4" \
22 | --transform ";NetRemap;client_subnet,client_subnet2,client_addr_vs_rcode,ipv6_rsn_abusers;net=16" \
23 | --generator ";client_subnet_authority;csv=$base/ipv4-address-space.csv;csv=$base/ipv6-unicast-address-assignments.csv" \
24 | --generator ";client_subnet_country;path=$HOME/GeoIP" \
25 | --xml "$base/1563520620.dscdata.xml" >/dev/null
26 |
27 | ! dsc-datatool \
28 | -vvv \
29 | -s test-server \
30 | -n test-node \
31 | --output ";InfluxDB;dml=1;database=dsc" \
32 | --transform ";Labler;*;yaml=$base/labler.yaml" \
33 | --transform ";ReRanger;rcode_vs_replylen;range=/64;pad_to=5" \
34 | --transform ";ReRanger;qtype_vs_qnamelen;range=/16;pad_to=3" \
35 | --transform ";ReRanger;client_port_range;key=low;range=/2048;pad_to=5" \
36 | --transform ";ReRanger;edns_bufsiz,priming_queries;key=low;range=/512;pad_to=5;allow_invalid_keys=1" \
37 | --transform ";ReRanger;priming_responses;key=low;range=/128;pad_to=4" \
38 | --transform ";NetRemap;client_subnet,client_subnet2,client_addr_vs_rcode,ipv6_rsn_abusers;net=16" \
39 | --generator ";client_subnet_authority;csv=$base/ipv4-address-space.csv;csv=$base/ipv6-unicast-address-assignments.csv" \
40 | --generator ";client_subnet_country;path=$HOME/GeoIP" \
41 | --xml "$base" >/dev/null
42 |
43 | dsc-datatool \
44 | -vvv \
45 | -s test-server \
46 | -n test-node \
47 | --output ";InfluxDB;dml=1;database=dsc" \
48 | --transform ";ReRanger;rcode_vs_replylen;range=/64;pad_to=5" \
49 | --transform ";ReRanger;qtype_vs_qnamelen;range=/16;pad_to=3" \
50 | --transform ";ReRanger;client_port_range;key=low;range=/2048;pad_to=5" \
51 | --transform ";ReRanger;edns_bufsiz,priming_queries;key=low;range=/512;pad_to=5;allow_invalid_keys=1" \
52 | --transform ";ReRanger;priming_responses;key=low;range=/128;pad_to=4" \
53 | --transform ";NetRemap;client_subnet,client_subnet2,client_addr_vs_rcode,ipv6_rsn_abusers;net=16" \
54 | --generator ";client_subnet_authority;csv=$base/ipv4-address-space.csv;csv=$base/ipv6-unicast-address-assignments.csv" \
55 | --generator ";client_subnet_country;path=$HOME/GeoIP" \
56 | --dat "$base/20190719" >/dev/null
57 |
58 | dsc-datatool -vvvvvvv --list >/dev/null
59 | ! dsc-datatool -s test -n test --output ";InfluxDB;test=a;test=b;test=c" >/dev/null
60 | ! dsc-datatool -s test -n test --generator does_not_exist >/dev/null
61 | ! dsc-datatool -s test -n test --generator does_not_exist,really_does_not_exist >/dev/null
62 | ! dsc-datatool -s test -n test --transform ";does_not_exist;*" >/dev/null
63 | ! dsc-datatool -s test -n test --transform ";ReRanger;a,a,a;range=/8" >/dev/null
64 | ! dsc-datatool -s test -n test --output does_not_exists >/dev/null
65 | ! dsc-datatool -s test -n test --dataset a --dataset b --dataset c,d,e >/dev/null
66 | ! dsc-datatool -s test -n test --dat "$base/coverage.sh" >/dev/null
67 |
--------------------------------------------------------------------------------
/dsc_datatool/output/prometheus.py:
--------------------------------------------------------------------------------
1 | """dsc_datatool.output.prometheus
2 |
3 | See `man dsc-datatool-output prometheus`.
4 |
5 | Part of dsc_datatool.
6 |
7 | :copyright: 2024 OARC, Inc.
8 | """
9 |
10 | import re
11 | import sys
12 | import atexit
13 |
14 | from dsc_datatool import Output, args, encoding
15 |
16 |
17 | _re = re.compile(r'([\\\n"])')
18 |
19 |
20 | def _key(key):
21 | return re.sub(_re, r'\\\1', key)
22 |
23 |
24 | def _val(val):
25 | ret = re.sub(_re, r'\\\1', val)
26 | if ret == '':
27 | return '""'
28 | return '"%s"' % ret
29 |
30 |
31 | class Prometheus(Output):
32 | show_timestamp = True
33 | start_timestamp = True
34 | fh = None
35 | type_def = ''
36 | type_printed = False
37 | prefix = ''
38 |
39 |
40 | def __init__(self, opts):
41 | Output.__init__(self, opts)
42 | timestamp = opts.get('timestamp', 'start')
43 | if timestamp == 'hide':
44 | self.show_timestamp = False
45 | elif timestamp == 'start':
46 | pass
47 | elif timestamp == 'stop':
48 | self.start_timestamp = False
49 | else:
50 | raise Exception('timestamp option invalid')
51 | file = opts.get('file', None)
52 | append = opts.get('append', False)
53 | if file:
54 | if append:
55 | self.fh = open(file, 'a', encoding=encoding)
56 | else:
57 | self.fh = open(file, 'w', encoding=encoding)
58 | atexit.register(self.close)
59 | else:
60 | self.fh = sys.stdout
61 | self.prefix = opts.get('prefix', '')
62 |
63 |
64 | def close(self):
65 | if self.fh:
66 | self.fh.close()
67 | self.fh = None
68 |
69 |
70 | def _process(self, tags, timestamp, dimension, fh):
71 | if dimension.dimensions is None:
72 | return
73 |
74 | if len(dimension.dimensions) > 0:
75 | if not (dimension.name == 'All' and dimension.value == 'ALL'):
76 | tags += ',%s=%s' % (_key(dimension.name.lower()), _val(dimension.value))
77 | for d2 in dimension.dimensions:
78 | self._process(tags, timestamp, d2, fh)
79 | return
80 |
81 | if dimension.values is None:
82 | return
83 |
84 | if len(dimension.values) > 0:
85 | tags += ',%s=' % _key(dimension.name.lower())
86 |
87 | for k, v in dimension.values.items():
88 | if not self.type_printed:
89 | print(self.type_def, file=fh)
90 | self.type_printed = True
91 | if self.show_timestamp:
92 | print('%s%s} %s %s' % (tags, _val(k), v, timestamp), file=fh)
93 | else:
94 | print('%s%s} %s' % (tags, _val(k), v), file=fh)
95 |
96 |
97 | def process(self, datasets):
98 | for dataset in datasets:
99 | self.type_def = '# TYPE %s gauge' % _key(dataset.name.lower())
100 | self.type_printed = False
101 | tags = '%s%s{server=%s,node=%s' % (self.prefix, _key(dataset.name.lower()), _val(args.server), _val(args.node))
102 | if self.start_timestamp:
103 | timestamp = dataset.start_time * 1000
104 | else:
105 | timestamp = dataset.end_time * 1000
106 |
107 | for d in dataset.dimensions:
108 | self._process(tags, timestamp, d, self.fh)
109 |
110 |
111 | if sys.version_info[0] == 3 and sys.version_info[1] == 5: # pragma: no cover
112 | Output.__init_subclass__(Prometheus)
113 |
--------------------------------------------------------------------------------
/dsc_datatool/transformer/re_ranger.py:
--------------------------------------------------------------------------------
1 | """dsc_datatool.transformer.re_ranger
2 |
3 | See `man dsc-datatool-transformer reranger`.
4 |
5 | Part of dsc_datatool.
6 |
7 | :copyright: 2024 OARC, Inc.
8 | """
9 |
10 | import re
11 |
12 | from dsc_datatool import Transformer, args
13 |
14 |
15 | _key_re = re.compile(r'^(?:(\d+)|(\d+)-(\d+))$')
16 |
17 |
18 | class ReRanger(Transformer):
19 | key = None
20 | func = None
21 | allow_invalid_keys = None
22 | range = None
23 | split_by = None
24 |
25 |
26 | def __init__(self, opts):
27 | Transformer.__init__(self, opts)
28 | self.key = opts.get('key', 'mid')
29 | self.func = opts.get('func', 'sum')
30 | self.allow_invalid_keys = opts.get('allow_invalid_keys', False)
31 | self.range = opts.get('range', None)
32 |
33 | if self.allow_invalid_keys != False:
34 | self.allow_invalid_keys = True
35 |
36 | if self.range is None:
37 | raise Exception('range must be given')
38 | m = re.match(r'^/(\d+)$', self.range)
39 | if m is None:
40 | raise Exception('invalid range')
41 | self.split_by = int(m.group(1))
42 |
43 | if self.key != 'low' and self.key != 'mid' and self.key != 'high':
44 | raise Exception('invalid key %r' % self.key)
45 |
46 | if self.func != 'sum':
47 | raise Exception('invalid func %r' % self.func)
48 |
49 |
50 | def _process(self, dimension):
51 | global _key_re
52 |
53 | if not dimension.values:
54 | for d2 in dimension.dimensions:
55 | self._process(d2)
56 | return
57 |
58 | values = dimension.values
59 | dimension.values = {}
60 | skipped = None
61 |
62 | for k, v in values.items():
63 | low = None
64 | high = None
65 |
66 | m = _key_re.match(k)
67 | if m:
68 | low, low2, high = m.group(1, 2, 3)
69 | if high is None:
70 | low = int(low)
71 | high = low
72 | else:
73 | low = int(low2)
74 | high = int(high)
75 | elif k == args.skipped_key:
76 | continue
77 | elif k == args.skipped_sum_key:
78 | if skipped is None:
79 | skipped = v
80 | else:
81 | skipped += v
82 | continue
83 | elif self.allow_invalid_keys:
84 | dimension.values[k] = v
85 | continue
86 | else:
87 | raise Exception('invalid key %r' % k)
88 |
89 | if self.key == 'low':
90 | nkey = low
91 | elif self.key == 'mid':
92 | nkey = int(low + ( (high - low) / 2 ))
93 | else:
94 | nkey = high
95 |
96 | nkey = int(nkey / self.split_by) * self.split_by
97 | low = nkey
98 | high = nkey + self.split_by - 1
99 |
100 | if self.func == 'sum':
101 | if low != high:
102 | nkey = '%d-%d' % (low, high)
103 | else:
104 | nkey = str(nkey)
105 |
106 | if nkey in dimension.values:
107 | dimension.values[nkey] += v
108 | else:
109 | dimension.values[nkey] = v
110 |
111 | if skipped:
112 | dimension.values['skipped'] = skipped
113 |
114 |
115 | def process(self, datasets):
116 | for dataset in datasets:
117 | for dimension in dataset.dimensions:
118 | self._process(dimension)
119 |
120 |
121 | import sys
122 | if sys.version_info[0] == 3 and sys.version_info[1] == 5: # pragma: no cover
123 | Transformer.__init_subclass__(ReRanger)
124 |
--------------------------------------------------------------------------------
/tests/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -xe
2 |
3 | base=`dirname $0`
4 |
5 | dsc-datatool \
6 | -vvv \
7 | -s test-server \
8 | -n test-node \
9 | --output ";InfluxDB;dml=1;database=dsc" \
10 | --transform ";Labler;*;yaml=$base/labler.yaml" \
11 | --transform ";ReRanger;rcode_vs_replylen;range=/64;pad_to=5" \
12 | --transform ";ReRanger;qtype_vs_qnamelen;range=/16;pad_to=3" \
13 | --transform ";ReRanger;client_port_range;key=low;range=/2048;pad_to=5" \
14 | --transform ";ReRanger;edns_bufsiz,priming_queries;key=low;range=/512;pad_to=5;allow_invalid_keys=1" \
15 | --transform ";ReRanger;priming_responses;key=low;range=/128;pad_to=4" \
16 | --transform ";NetRemap;client_subnet,client_subnet2,client_addr_vs_rcode,ipv6_rsn_abusers;net=16" \
17 | --generator ";client_subnet_authority;csv=$base/ipv4-address-space.csv;csv=$base/ipv6-unicast-address-assignments.csv" \
18 | --xml "$base/1563520620.dscdata.xml" | sort -s > "$base/test.out"
19 |
20 | sort -s "$base/test.gold" > "$base/test.gold.tmp"
21 | diff -u "$base/test.gold.tmp" "$base/test.out"
22 |
23 | dsc-datatool \
24 | -vvv \
25 | -s test-server \
26 | -n test-node \
27 | --output ";InfluxDB;dml=1;database=dsc" \
28 | --transform ";Labler;*;yaml=$base/labler.yaml" \
29 | --transform ";ReRanger;rcode_vs_replylen;range=/64;pad_to=5" \
30 | --transform ";ReRanger;qtype_vs_qnamelen;range=/16;pad_to=3" \
31 | --transform ";ReRanger;client_port_range;key=low;range=/2048;pad_to=5" \
32 | --transform ";ReRanger;edns_bufsiz,priming_queries;key=low;range=/512;pad_to=5;allow_invalid_keys=1" \
33 | --transform ";ReRanger;priming_responses;key=low;range=/128;pad_to=4" \
34 | --transform ";NetRemap;client_subnet,client_subnet2,client_addr_vs_rcode,ipv6_rsn_abusers;net=16" \
35 | --generator ";client_subnet_authority;csv=$base/ipv4-address-space.csv;csv=$base/ipv6-unicast-address-assignments.csv" \
36 | --dat "$base/20190719" | sort -s > "$base/test.out"
37 |
38 | sort -s "$base/test.gold2" > "$base/test.gold2.tmp"
39 | diff -u "$base/test.gold2.tmp" "$base/test.out"
40 |
41 | dsc-datatool \
42 | -vvv \
43 | -s test-server \
44 | -n test-node \
45 | --output ";InfluxDB;dml=1;database=dsc" \
46 | --transform ";Labler;*;yaml=$base/labler.yaml" \
47 | --transform ";ReRanger;rcode_vs_replylen;range=/64;pad_to=5" \
48 | --transform ";ReRanger;qtype_vs_qnamelen;range=/16;pad_to=3" \
49 | --transform ";ReRanger;client_port_range;key=low;range=/2048;pad_to=5" \
50 | --transform ";ReRanger;edns_bufsiz,priming_queries;key=low;range=/512;pad_to=5;allow_invalid_keys=1" \
51 | --transform ";ReRanger;priming_responses;key=low;range=/128;pad_to=4" \
52 | --transform ";NetRemap;client_subnet,client_subnet2,client_addr_vs_rcode,ipv6_rsn_abusers;net=16" \
53 | --generator ";client_subnet_authority;csv=$base/ipv4-address-space.csv;csv=$base/ipv6-unicast-address-assignments.csv" \
54 | --xml "$base/1458044657.xml" | sort -s > "$base/test.out"
55 |
56 | sort -s "$base/test.gold3" > "$base/test.gold3.tmp"
57 | diff -u "$base/test.gold3.tmp" "$base/test.out"
58 |
59 | dsc-datatool \
60 | -vvv \
61 | -s test-server-åäö \
62 | -n test-node \
63 | --output ";InfluxDB;dml=1;database=dsc" \
64 | --transform ";Labler;*;yaml=$base/labler.yaml" \
65 | --transform ";ReRanger;rcode_vs_replylen;range=/64;pad_to=5" \
66 | --transform ";ReRanger;qtype_vs_qnamelen;range=/16;pad_to=3" \
67 | --transform ";ReRanger;client_port_range;key=low;range=/2048;pad_to=5" \
68 | --transform ";ReRanger;edns_bufsiz,priming_queries;key=low;range=/512;pad_to=5;allow_invalid_keys=1" \
69 | --transform ";ReRanger;priming_responses;key=low;range=/128;pad_to=4" \
70 | --transform ";NetRemap;client_subnet,client_subnet2,client_addr_vs_rcode,ipv6_rsn_abusers;net=16" \
71 | --generator ";client_subnet_authority;csv=$base/ipv4-address-space.csv;csv=$base/ipv6-unicast-address-assignments.csv" \
72 | --xml "$base/utf8.xml" | sort -s > "$base/test.out"
73 |
74 | sort -s "$base/test.gold4" > "$base/test.gold4.tmp"
75 | diff -u "$base/test.gold4.tmp" "$base/test.out"
76 |
--------------------------------------------------------------------------------
/tests/test.gold3:
--------------------------------------------------------------------------------
1 | # DML
2 | # CONTEXT-DATABASE: dsc
3 | pcap_stats,server=test-server,node=test-node,ifname=./1458044657.pcap.dist,pcap_stat=pkts_captured value=8 1458044655000000000
4 | label_count,server=test-server,node=test-node,labelcount=3 value=4 1458044655000000000
5 | label_count,server=test-server,node=test-node,labelcount=6 value=4 1458044655000000000
6 | third_ld_vs_rcode,server=test-server,node=test-node,rcode=0,thirdld=216.in-addr.arpa value=2 1458044655000000000
7 | third_ld_vs_rcode,server=test-server,node=test-node,rcode=0,thirdld=www.google.se value=1 1458044655000000000
8 | third_ld_vs_rcode,server=test-server,node=test-node,rcode=0,thirdld=www.google.com value=1 1458044655000000000
9 | second_ld_vs_rcode,server=test-server,node=test-node,rcode=0,secondld=in-addr.arpa value=2 1458044655000000000
10 | second_ld_vs_rcode,server=test-server,node=test-node,rcode=0,secondld=google.com value=1 1458044655000000000
11 | second_ld_vs_rcode,server=test-server,node=test-node,rcode=0,secondld=www.google.se value=1 1458044655000000000
12 | server,server=test-server,node=test-node,ip=8.8.8.8 value=8 1458044655000000000
13 | qr_aa_bits,server=test-server,node=test-node,direction=else,qraabits=qr\=0\,aa\=0 value=4 1458044655000000000
14 | qr_aa_bits,server=test-server,node=test-node,direction=else,qraabits=qr\=1\,aa\=0 value=4 1458044655000000000
15 | qname,server=test-server,node=test-node,name=100.209.58.216.in-addr.arpa value=2 1458044655000000000
16 | qname,server=test-server,node=test-node,name=www.google.se value=2 1458044655000000000
17 | qname,server=test-server,node=test-node,name=131.209.58.216.in-addr.arpa value=2 1458044655000000000
18 | qname,server=test-server,node=test-node,name=www.google.com value=2 1458044655000000000
19 | qclass,server=test-server,node=test-node,class=1 value=8 1458044655000000000
20 | dns_ip_version,server=test-server,node=test-node,version=IPv4 value=8 1458044655000000000
21 | ip_version,server=test-server,node=test-node,version=IPv4 value=8 1458044655000000000
22 | direction_vs_ipproto,server=test-server,node=test-node,direction=else,ipproto=udp value=8 1458044655000000000
23 | client_port,server=test-server,node=test-node,port=59978 value=4 1458044655000000000
24 | client_port,server=test-server,node=test-node,port=0 value=1 1458044655000000000
25 | client_port,server=test-server,node=test-node,port=53 value=1 1458044655000000000
26 | client_port,server=test-server,node=test-node,port=44275 value=1 1458044655000000000
27 | client_port,server=test-server,node=test-node,port=57483 value=1 1458044655000000000
28 | client_port_range,server=test-server,node=test-node,portrange=43008-45055 value=1 1458044655000000000
29 | client_port_range,server=test-server,node=test-node,portrange=55296-57343 value=1 1458044655000000000
30 | client_port_range,server=test-server,node=test-node,portrange=57344-59391 value=2 1458044655000000000
31 | transport_vs_qtype,server=test-server,node=test-node,transport=udp,qtype=A value=2 1458044655000000000
32 | transport_vs_qtype,server=test-server,node=test-node,transport=udp,qtype=PTR value=2 1458044655000000000
33 | tc_bit,server=test-server,node=test-node,tc=clr value=8 1458044655000000000
34 | rd_bit,server=test-server,node=test-node,rd=set value=4 1458044655000000000
35 | do_bit,server=test-server,node=test-node,d0=clr value=4 1458044655000000000
36 | edns_bufsiz,server=test-server,node=test-node,ednsbufsiz=None value=4 1458044655000000000
37 | edns_version,server=test-server,node=test-node,ednsversion=none value=4 1458044655000000000
38 | idn_qname,server=test-server,node=test-node,idnqname=normal value=4 1458044655000000000
39 | client_addr_vs_rcode,server=test-server,node=test-node,rcode=NoError,clientaddr=172.17.0.0 value=4 1458044655000000000
40 | client_subnet2,server=test-server,node=test-node,class=ok,clientsubnet=172.17.0.0 value=3 1458044655000000000
41 | client_subnet2,server=test-server,node=test-node,class=non-auth-tld,clientsubnet=172.17.0.0 value=1 1458044655000000000
42 | certain_qnames_vs_qtype,server=test-server,node=test-node,certainqnames=else,qtype=A value=2 1458044655000000000
43 | certain_qnames_vs_qtype,server=test-server,node=test-node,certainqnames=else,qtype=PTR value=2 1458044655000000000
44 | qtype_vs_tld,server=test-server,node=test-node,qtype=A,tld=com value=1 1458044655000000000
45 | qtype_vs_tld,server=test-server,node=test-node,qtype=A,tld=google.se value=1 1458044655000000000
46 | qtype_vs_tld,server=test-server,node=test-node,qtype=PTR,tld=arpa value=2 1458044655000000000
47 | qtype_vs_qnamelen,server=test-server,node=test-node,qtype=A,qnamelen=0-15 value=2 1458044655000000000
48 | qtype_vs_qnamelen,server=test-server,node=test-node,qtype=PTR,qnamelen=16-31 value=2 1458044655000000000
49 | client_subnet,server=test-server,node=test-node,clientsubnet=172.17.0.0 value=4 1458044655000000000
50 | rcode_vs_replylen,server=test-server,node=test-node,rcode=NoError,replylen=128-191 value=2 1458044655000000000
51 | rcode_vs_replylen,server=test-server,node=test-node,rcode=NoError,replylen=0-63 value=2 1458044655000000000
52 | opcode,server=test-server,node=test-node,opcode=NoError value=4 1458044655000000000
53 | rcode,server=test-server,node=test-node,rcode=NoError value=4 1458044655000000000
54 | qtype,server=test-server,node=test-node,qtype=A value=2 1458044655000000000
55 | qtype,server=test-server,node=test-node,qtype=PTR value=2 1458044655000000000
56 | client_subnet_authority,server=test-server,node=test-node,clientauthority=ARIN value=4 1458044655000000000
57 |
--------------------------------------------------------------------------------
/man/man1/dsc-datatool.1:
--------------------------------------------------------------------------------
1 | .TH "dsc-datatool" "1"
2 | .SH NAME
3 | dsc-datatool \- Tool for converting, exporting, merging and transforming DSC data.
4 | .SH SYNOPSIS
5 | .SY dsc-datatool
6 | .OP \-h
7 | .OP \-c CONF
8 | .OP \-s SERVER
9 | .OP \-n NODE
10 | .OP \-x XML
11 | .OP \-d DAT
12 | .OP \-\-dataset DATASET
13 | .OP \-o OUTPUT
14 | .OP \-t TRANSFORM]
15 | .OP \-g GENERATOR
16 | .OP \-\-list
17 | .OP \-\-skipped\-key SKIPPED_KEY
18 | .OP \-\-skipped\-sum\-key SKIPPED_SUM_KEY
19 | .OP \-v
20 | .OP \-V
21 | .YS
22 | .SH DESCRIPTION
23 | Tool for converting, exporting, merging and transforming DSC data.
24 |
25 | Please have a look at the wiki article on how to set this up using
26 | Influx DB and Grafana.
27 |
28 | https://codeberg.org/DNS-OARC/dsc-datatool/wiki/Setting-up-a-test-Grafana
29 | .SH OPTIONS
30 | .TP
31 | .B -h, --help
32 | show this help message and exit
33 | .TP
34 | .BI "-c " CONF ", --conf " CONF
35 | Not implemented
36 | .TP
37 | .BI "-s " SERVER ", --server " SERVER
38 | Specify the server for where the data comes from. (required)
39 | .TP
40 | .BI "-n " NODE ", --node " NODE
41 | Specify the node for where the data comes from. (required)
42 | .TP
43 | .BI "-x " XML ", --xml " XML
44 | Read DSC data from the given file or directory, can be specified multiple
45 | times.
46 | If a directory is given then all files ending with .xml will be read.
47 | .TP
48 | .BI "-d " DAT ", --dat " DAT
49 | Read DSC data from the given directory, can be specified multiple times.
50 | Note that the DAT format is depended on the filename to know what type of
51 | data it is.
52 | .TP
53 | .BI "--dataset " DATASET
54 | Specify that only the list of datasets will be processed, the list is
55 | comma separated and the option can be given multiple times.
56 | .TP
57 | .BI "-o " OUTPUT ", --output " OUTPUT
58 | .I OUTPUT
59 | has the following format that uses
60 | .I output
61 | to specify the output module and
62 | .I sep
63 | as an options separator.
64 |
65 | .EX
66 |