mirror of
https://github.com/outbackdingo/nDPId.git
synced 2026-01-28 02:19:37 +00:00
Compare commits
461 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d629fda779 | ||
|
|
643aa49d34 | ||
|
|
8dfaa7c86c | ||
|
|
59caa5231e | ||
|
|
9c0f5141bc | ||
|
|
e8ef267e0a | ||
|
|
2651833c58 | ||
|
|
bd7df393fe | ||
|
|
88cfecdf95 | ||
|
|
a91aab493c | ||
|
|
fe42e998d0 | ||
|
|
22e44c1e0b | ||
|
|
d8cad33a70 | ||
|
|
37989db0bb | ||
|
|
19f80ba163 | ||
|
|
c8c58e0b16 | ||
|
|
6d3dc99fad | ||
|
|
b8d3cf9e8f | ||
|
|
510b03cbcd | ||
|
|
66aca303b6 | ||
|
|
0e7e5216d8 | ||
|
|
7ab7bb3772 | ||
|
|
a47bc9caa3 | ||
|
|
7d94632811 | ||
|
|
2c81f116bf | ||
|
|
49b058d2d3 | ||
|
|
fea52d98ca | ||
|
|
02b686241e | ||
|
|
2cb0d7941b | ||
|
|
97e60ad7ec | ||
|
|
eea5a49638 | ||
|
|
a9934e9c9e | ||
|
|
644fa2dfb3 | ||
|
|
1a6b1feda9 | ||
|
|
648dedc7ba | ||
|
|
19036951c7 | ||
|
|
4e7e361d84 | ||
|
|
9809ae4ea0 | ||
|
|
97387d0f1c | ||
|
|
46ef266139 | ||
|
|
ae6864d4e4 | ||
|
|
f3c8ffe6c1 | ||
|
|
07d6018109 | ||
|
|
dd909adeb8 | ||
|
|
8848420a72 | ||
|
|
f8181d7f6a | ||
|
|
b747255a5d | ||
|
|
a52a37ef78 | ||
|
|
ae95c95617 | ||
|
|
42c54d3755 | ||
|
|
bb870cb98f | ||
|
|
e262227d65 | ||
|
|
899e5a80d6 | ||
|
|
053818b242 | ||
|
|
4048a8c300 | ||
|
|
09b246dbfa | ||
|
|
471ea83493 | ||
|
|
064bd3aefa | ||
|
|
acd9e871b6 | ||
|
|
b9465c09d8 | ||
|
|
3a4b7b0860 | ||
|
|
34f01b90e3 | ||
|
|
7b91ad8458 | ||
|
|
442900bc14 | ||
|
|
0a4f3cb0c8 | ||
|
|
4bed2a791f | ||
|
|
1aa7d9bdb6 | ||
|
|
bd269c9ead | ||
|
|
7e4c69635a | ||
|
|
9105b393e1 | ||
|
|
9efdecf4ef | ||
|
|
8c114e4916 | ||
|
|
a733d536ad | ||
|
|
9fc35e7a7e | ||
|
|
ce9752af16 | ||
|
|
f7933d0fdb | ||
|
|
d5a84ce630 | ||
|
|
ce5f448d3b | ||
|
|
2b48eb0514 | ||
|
|
ddc96ba614 | ||
|
|
7b2cd268bf | ||
|
|
817559ffa7 | ||
|
|
25944e2089 | ||
|
|
5423797267 | ||
|
|
7e126c205e | ||
|
|
7d58703bdb | ||
|
|
ae36f8df6c | ||
|
|
8c5ee1f7bb | ||
|
|
9969f955dc | ||
|
|
2c771c54b0 | ||
|
|
fb1dcc71de | ||
|
|
071a9bcb91 | ||
|
|
9a14454d3c | ||
|
|
f9d9849300 | ||
|
|
efed6f196e | ||
|
|
3e2ce661f0 | ||
|
|
76e1ea0598 | ||
|
|
0e792ba301 | ||
|
|
9ef17b7bd8 | ||
|
|
1c9aa85485 | ||
|
|
aef9d629f0 | ||
|
|
f97b3880b6 | ||
|
|
c55429c131 | ||
|
|
7bebd7b2c7 | ||
|
|
335708d3e3 | ||
|
|
2a0161c1bb | ||
|
|
adb8fe96f5 | ||
|
|
4efe7e43a2 | ||
|
|
5e4005162b | ||
|
|
a230eaf061 | ||
|
|
68e0c1f280 | ||
|
|
8271f15e25 | ||
|
|
f6f3a4daab | ||
|
|
762e6d36bf | ||
|
|
930aaf9276 | ||
|
|
165b18c829 | ||
|
|
1fbfd46fe8 | ||
|
|
5290f76b5f | ||
|
|
f4d0f80711 | ||
|
|
187ebeb4df | ||
|
|
71d2fcc491 | ||
|
|
86aaf0e808 | ||
|
|
e822bb6145 | ||
|
|
4c91038274 | ||
|
|
53126a0af9 | ||
|
|
15608bb571 | ||
|
|
e93a4c9a81 | ||
|
|
b46f15de03 | ||
|
|
c7eace426c | ||
|
|
33560d64d2 | ||
|
|
675640b0e6 | ||
|
|
5e5f268b3c | ||
|
|
7ef7667da3 | ||
|
|
d43a3d1436 | ||
|
|
b6e4162116 | ||
|
|
717d66b0e7 | ||
|
|
791b27219d | ||
|
|
a487e53015 | ||
|
|
aeb6e6f536 | ||
|
|
8af37b3770 | ||
|
|
8949ba39e6 | ||
|
|
ea968180a2 | ||
|
|
556025b34d | ||
|
|
feb2583ef6 | ||
|
|
7368f222db | ||
|
|
a007a907da | ||
|
|
876aef98e1 | ||
|
|
88cf57a16f | ||
|
|
7e81f5b1b7 | ||
|
|
8acf2d7273 | ||
|
|
71d933b0cd | ||
|
|
fbe07fd882 | ||
|
|
5432b06665 | ||
|
|
142a435bf6 | ||
|
|
f5c5bc88a7 | ||
|
|
53d8a28582 | ||
|
|
37f3770e3e | ||
|
|
7368d34d8d | ||
|
|
ff77bab398 | ||
|
|
d274a06176 | ||
|
|
a5dcc17396 | ||
|
|
3416db11dc | ||
|
|
830174c7b5 | ||
|
|
bb9f02719d | ||
|
|
f38f1ec37f | ||
|
|
fa7e76cc75 | ||
|
|
b0c343a795 | ||
|
|
d5266b7f44 | ||
|
|
82934b7271 | ||
|
|
4920b2a4be | ||
|
|
8ebaccc27d | ||
|
|
dcb595e161 | ||
|
|
b667f9e1da | ||
|
|
55c8a848d3 | ||
|
|
d80ea84d2e | ||
|
|
b1e679b0bb | ||
|
|
949fc0c35e | ||
|
|
5d56288a11 | ||
|
|
84b12cd02c | ||
|
|
93498fff02 | ||
|
|
1b67927169 | ||
|
|
17c21e1d27 | ||
|
|
5fb706e9a6 | ||
|
|
5335d84fe5 | ||
|
|
32ab500eb0 | ||
|
|
e124f2d660 | ||
|
|
6ff8982ffb | ||
|
|
315dc32baf | ||
|
|
3d0c06ef54 | ||
|
|
8dca2b546a | ||
|
|
e134eef5bb | ||
|
|
d29efd4d7c | ||
|
|
44adfc0b7d | ||
|
|
dfd0449306 | ||
|
|
07f2c2d9cc | ||
|
|
73b8c378f2 | ||
|
|
a0e0611c56 | ||
|
|
7f8e01d442 | ||
|
|
835a7bafb1 | ||
|
|
a7ac83385b | ||
|
|
0a0342ce28 | ||
|
|
7515c1b072 | ||
|
|
be07c16c0e | ||
|
|
e42e3fe406 | ||
|
|
96b0a8a474 | ||
|
|
091fd4d116 | ||
|
|
dfb8d3379f | ||
|
|
a7bd3570b0 | ||
|
|
b01498f011 | ||
|
|
cc60e819e8 | ||
|
|
5234f4621b | ||
|
|
86ac09a8db | ||
|
|
4b3031245d | ||
|
|
2b881d56e7 | ||
|
|
dd4357c238 | ||
|
|
7b15838696 | ||
|
|
0e31829401 | ||
|
|
d9f304e4b0 | ||
|
|
ebb439d959 | ||
|
|
79834df457 | ||
|
|
4b923bdf44 | ||
|
|
ba8236c1f7 | ||
|
|
d915530feb | ||
|
|
7bd8081cd2 | ||
|
|
bc0a5782cc | ||
|
|
8a8de12fb3 | ||
|
|
c57ace2fd3 | ||
|
|
344934b7d9 | ||
|
|
22ba5d5103 | ||
|
|
7217b90cd1 | ||
|
|
74a9f7d86b | ||
|
|
57d8dda350 | ||
|
|
425617abdf | ||
|
|
92b3c76446 | ||
|
|
967381a599 | ||
|
|
d107560049 | ||
|
|
c8ec505b9c | ||
|
|
2b1db0a556 | ||
|
|
d8c20d37e5 | ||
|
|
5a9b40779d | ||
|
|
d0c070a800 | ||
|
|
8a936a5072 | ||
|
|
c9514136b7 | ||
|
|
a4e5bab9b2 | ||
|
|
b76a0c4607 | ||
|
|
c9da8b0fd9 | ||
|
|
ca355b1fdb | ||
|
|
99accd03a2 | ||
|
|
225f4b3fb6 | ||
|
|
a8d46ef343 | ||
|
|
aafc72a44b | ||
|
|
0a959993bc | ||
|
|
595bd5c5e3 | ||
|
|
4236aafa0d | ||
|
|
23816f1403 | ||
|
|
42aad33ec8 | ||
|
|
c71284291e | ||
|
|
58439a6761 | ||
|
|
5e313f43f9 | ||
|
|
a3d20c17d1 | ||
|
|
c0717c7e6c | ||
|
|
470ed99eaf | ||
|
|
ac3757a367 | ||
|
|
07efb1efd4 | ||
|
|
afe873c0de | ||
|
|
3dcc13b052 | ||
|
|
464450486b | ||
|
|
655393e953 | ||
|
|
e9443d7618 | ||
|
|
4e19ab929c | ||
|
|
c5930e3510 | ||
|
|
d21a38cf02 | ||
|
|
ced5f5d4b4 | ||
|
|
60741d5649 | ||
|
|
8b81b170d3 | ||
|
|
2c95b31210 | ||
|
|
532961af33 | ||
|
|
64f6abfdbe | ||
|
|
77ee336cc9 | ||
|
|
9b78939096 | ||
|
|
57c5d8532b | ||
|
|
869d4de271 | ||
|
|
ce567ae5b7 | ||
|
|
36e428fc89 | ||
|
|
ea1698504c | ||
|
|
bc346a28f4 | ||
|
|
e629dd59cd | ||
|
|
7515c8aeec | ||
|
|
25f4ef74ac | ||
|
|
d55e397929 | ||
|
|
d3f99f21e6 | ||
|
|
c63cbec26d | ||
|
|
805aef5de8 | ||
|
|
2d14509f04 | ||
|
|
916d2df6ea | ||
|
|
46c8fc5219 | ||
|
|
e5f4af4890 | ||
|
|
cd22d56056 | ||
|
|
49352698a0 | ||
|
|
6292102f93 | ||
|
|
80f8448834 | ||
|
|
9bf4f31418 | ||
|
|
4069816d69 | ||
|
|
bb633bde22 | ||
|
|
20fc74f527 | ||
|
|
2ede930eec | ||
|
|
4654faf381 | ||
|
|
b7a17d62c7 | ||
|
|
ac46f3841f | ||
|
|
be3f466373 | ||
|
|
b7d8564b65 | ||
|
|
49ea4f8474 | ||
|
|
b6060b897e | ||
|
|
14f6b87551 | ||
|
|
74f71643da | ||
|
|
2103ee0811 | ||
|
|
36f1786bde | ||
|
|
9a28475bba | ||
|
|
28971cd764 | ||
|
|
3c7bd6a4ba | ||
|
|
08f263e409 | ||
|
|
ab7f7d05f3 | ||
|
|
015a739efd | ||
|
|
31715295d9 | ||
|
|
06bce24c0e | ||
|
|
efaa76e978 | ||
|
|
b3e9af495c | ||
|
|
b8cfe1d6d3 | ||
|
|
d4633c1192 | ||
|
|
aca1615dc1 | ||
|
|
94aa02b298 | ||
|
|
20ced3e636 | ||
|
|
83409e5b79 | ||
|
|
3bc6627dcc | ||
|
|
7594180301 | ||
|
|
a992c79ab6 | ||
|
|
6fe5d1da69 | ||
|
|
38c71af2f4 | ||
|
|
ac2e5ed796 | ||
|
|
f9bd7d29ce | ||
|
|
c5c7d83c97 | ||
|
|
70f517b040 | ||
|
|
dcf78ad3ed | ||
|
|
d646ec5ab4 | ||
|
|
dea30501a4 | ||
|
|
d9fadae718 | ||
|
|
5e09a00062 | ||
|
|
d0b0a50609 | ||
|
|
e2e7c82d7f | ||
|
|
0fd59f060e | ||
|
|
905545487d | ||
|
|
2cb2c86cb5 | ||
|
|
8c092dacfe | ||
|
|
96b9129918 | ||
|
|
ae37631e23 | ||
|
|
ef94b83a62 | ||
|
|
fc442180da | ||
|
|
a606586a32 | ||
|
|
4a397ac646 | ||
|
|
28602ca095 | ||
|
|
b5d4da8793 | ||
|
|
a80b6d7271 | ||
|
|
cdaeb1632e | ||
|
|
2a8883a96e | ||
|
|
664a8a077d | ||
|
|
77a87254b6 | ||
|
|
3caf7727fd | ||
|
|
f5b0021413 | ||
|
|
73ca7fff3c | ||
|
|
4fde63b5c2 | ||
|
|
0385653023 | ||
|
|
a46fc4153d | ||
|
|
22a8d04c74 | ||
|
|
9aeff586bd | ||
|
|
c7bf94e9f1 | ||
|
|
a2547321bb | ||
|
|
c283b89afd | ||
|
|
db83f82d29 | ||
|
|
645aeaf5b4 | ||
|
|
9f9e881b3f | ||
|
|
65a9e5a18d | ||
|
|
c0b7bdacbc | ||
|
|
daaaa61519 | ||
|
|
ed1647b944 | ||
|
|
dd35d9da3f | ||
|
|
f884a538ce | ||
|
|
41757ecf1c | ||
|
|
6f1f9e65ea | ||
|
|
d0985a5732 | ||
|
|
e09dd8509f | ||
|
|
29c72fb30b | ||
|
|
46f68501d5 | ||
|
|
9db048c9d9 | ||
|
|
cb80c415d8 | ||
|
|
6fd6dff14d | ||
|
|
f9e4c58854 | ||
|
|
1a0d7ddbfa | ||
|
|
7022d0b1c5 | ||
|
|
80e1eedbef | ||
|
|
4bae9d0344 | ||
|
|
29a1b13e7a | ||
|
|
9e07a57566 | ||
|
|
a35fc1d5ea | ||
|
|
cfecf3e110 | ||
|
|
25b974af67 | ||
|
|
d389f04135 | ||
|
|
9075706714 | ||
|
|
1f6d1fbd67 | ||
|
|
d93c33aa74 | ||
|
|
8ecd1b48ef | ||
|
|
3af8de5a58 | ||
|
|
315f90f982 | ||
|
|
fe77c44e3f | ||
|
|
3726311276 | ||
|
|
a523c348f3 | ||
|
|
5a6b2aa261 | ||
|
|
992d3a207d | ||
|
|
7829bfe4e6 | ||
|
|
4fa1694b05 | ||
|
|
c5be804725 | ||
|
|
655f38b68f | ||
|
|
1fa53c5bf8 | ||
|
|
4edf3bf7e6 | ||
|
|
8e096b19c1 | ||
|
|
2a5e5a020b | ||
|
|
e54c2df63b | ||
|
|
c152e41cfb | ||
|
|
aa89800ff9 | ||
|
|
ea0b04d648 | ||
|
|
6faded3cc7 | ||
|
|
d48508b4af | ||
|
|
f4c8d96dd9 | ||
|
|
3a76035570 | ||
|
|
c32461b032 | ||
|
|
6f04807236 | ||
|
|
19e4038ce5 | ||
|
|
7d6366ebfc | ||
|
|
114365a480 | ||
|
|
db87d45edb | ||
|
|
fac7648326 | ||
|
|
98b11f814f | ||
|
|
e20280cb43 | ||
|
|
4d6ea33aa4 | ||
|
|
55ecf068b3 | ||
|
|
d3ebb84ce4 | ||
|
|
7daeee141d | ||
|
|
a41ddafa88 | ||
|
|
30502ff0a0 | ||
|
|
5954e46340 | ||
|
|
54e0601fec | ||
|
|
382706cd20 | ||
|
|
96dc563d91 | ||
|
|
12e0ae98b6 | ||
|
|
2a59c0513c | ||
|
|
e3d1a8a772 | ||
|
|
4b6ead68a1 | ||
|
|
9a1c2d0ea7 | ||
|
|
db39772aa7 | ||
|
|
9ffaeef24d | ||
|
|
3a0fbe7433 | ||
|
|
da4942b41c |
19
.circleci/config.yml
Normal file
19
.circleci/config.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
version: 2.1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
docker:
|
||||||
|
- image: ubuntu:latest
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: export DEBIAN_FRONTEND=noninteractive
|
||||||
|
- run: apt-get update -qq
|
||||||
|
- run: |
|
||||||
|
env DEBIAN_FRONTEND=noninteractive \
|
||||||
|
apt-get install -y -qq \
|
||||||
|
coreutils wget git unzip make cmake binutils gcc g++ autoconf automake flex bison texinfo \
|
||||||
|
libtool pkg-config gettext libjson-c-dev flex bison libpcap-dev zlib1g-dev
|
||||||
|
- run: |
|
||||||
|
cmake -S . -B build -DENABLE_SYSTEMD=ON -DBUILD_EXAMPLES=ON -DBUILD_NDPI=ON
|
||||||
|
- run: |
|
||||||
|
cmake --build build --verbose
|
||||||
38
.github/workflows/build-archlinux.yml
vendored
Normal file
38
.github/workflows/build-archlinux.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
name: ArchLinux PKGBUILD
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- tmp
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
CMAKE_C_FLAGS: -Werror
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Prepare for ArchLinux packaging
|
||||||
|
run: |
|
||||||
|
sudo chmod -R 0777 .
|
||||||
|
mv -v packages/archlinux packages/ndpid-testing
|
||||||
|
- uses: 2m/arch-pkgbuild-builder@v1.16
|
||||||
|
with:
|
||||||
|
debug: true
|
||||||
|
target: 'pkgbuild'
|
||||||
|
pkgname: 'packages/ndpid-testing'
|
||||||
|
- name: Upload PKG
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: nDPId-archlinux-packages
|
||||||
|
path: packages/ndpid-testing/*.pkg.tar.zst
|
||||||
59
.github/workflows/build-centos.yml
vendored
Normal file
59
.github/workflows/build-centos.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
name: CentOs
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- tmp
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
centos8:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: 'centos:8'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Install CentOs Prerequisites
|
||||||
|
run: |
|
||||||
|
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
|
||||||
|
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
|
||||||
|
yum -y update
|
||||||
|
yum -y install curl gpg
|
||||||
|
curl 'https://packages.ntop.org/centos/ntop.repo' > /etc/yum.repos.d/ntop.repo
|
||||||
|
curl 'https://packages.ntop.org/centos/RPM-GPG-KEY-deri' | gpg --import
|
||||||
|
yum -y install yum-utils dnf-plugins-core epel-release
|
||||||
|
dnf config-manager --set-enabled powertools
|
||||||
|
yum -y update
|
||||||
|
yum -y install rpm-build gcc gcc-c++ autoconf automake make cmake flex bison gettext pkg-config libtool ndpi-dev libpcap-devel zlib-devel python3.8 git wget unzip /usr/lib64/libasan.so.5.0.0 /usr/lib64/libubsan.so.1.0.0
|
||||||
|
repoquery -l ndpi-dev
|
||||||
|
- name: Configure nDPId
|
||||||
|
run: |
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DENABLE_SYSTEMD=ON -DBUILD_EXAMPLES=ON -DENABLE_SANITIZER=ON -DNDPI_NO_PKGCONFIG=ON -DSTATIC_LIBNDPI_INSTALLDIR=/usr
|
||||||
|
- name: Build nDPId
|
||||||
|
run: |
|
||||||
|
make -C build all VERBOSE=1
|
||||||
|
- name: CPack RPM
|
||||||
|
run: |
|
||||||
|
cd ./build && cpack -G RPM && cd ..
|
||||||
|
- name: Upload RPM
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: nDPId-centos-packages
|
||||||
|
path: build/*.rpm
|
||||||
|
- name: Upload on Failure
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: autoconf-config-log
|
||||||
|
path: |
|
||||||
|
build/CMakeCache.txt
|
||||||
|
libnDPI/config.log
|
||||||
25
.github/workflows/build-docker.yml
vendored
Normal file
25
.github/workflows/build-docker.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
name: Docker Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
tags: utoni/ndpid:latest
|
||||||
39
.github/workflows/build-freebsd.yml
vendored
Normal file
39
.github/workflows/build-freebsd.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
name: FreeBSD Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# At the end of every day
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- tmp
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Build and Test
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Test in FreeBSD
|
||||||
|
id: test
|
||||||
|
uses: vmactions/freebsd-vm@main
|
||||||
|
with:
|
||||||
|
usesh: true
|
||||||
|
prepare: |
|
||||||
|
pkg install -y bash autoconf automake cmake gmake libtool gettext pkgconf gcc \
|
||||||
|
git wget unzip flock \
|
||||||
|
json-c flex bison libpcap curl openssl dbus
|
||||||
|
run: |
|
||||||
|
echo "Working Directory: $(pwd)"
|
||||||
|
echo "User.............: $(whoami)"
|
||||||
|
echo "FreeBSD Version..: $(freebsd-version)"
|
||||||
|
# TODO: Make examples I/O event agnostic i.e. use nio
|
||||||
|
cmake -S . -B build -DBUILD_NDPI=ON -DBUILD_EXAMPLES=OFF #-DENABLE_CURL=ON -DENABLE_DBUS=ON
|
||||||
|
cmake --build build
|
||||||
54
.github/workflows/build-openwrt.yml
vendored
Normal file
54
.github/workflows/build-openwrt.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
name: OpenWrt Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# At the end of every day
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- tmp
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: ${{ matrix.arch }} ${{ matrix.target }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- arch: arm_cortex-a9_vfpv3-d16
|
||||||
|
target: mvebu-cortexa9
|
||||||
|
|
||||||
|
- arch: arm_cortex-a15_neon-vfpv4
|
||||||
|
target: armvirt-32
|
||||||
|
|
||||||
|
- arch: x86_64
|
||||||
|
target: x86-64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
uses: openwrt/gh-action-sdk@main
|
||||||
|
env:
|
||||||
|
ARCH: ${{ matrix.arch }}-snapshot
|
||||||
|
FEED_DIR: ${{ github.workspace }}/packages/openwrt
|
||||||
|
FEEDNAME: ndpid_openwrt_packages_ci
|
||||||
|
PACKAGES: nDPId-testing
|
||||||
|
V: s
|
||||||
|
|
||||||
|
- name: Store packages
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: nDPId-${{ matrix.arch}}-${{ matrix.target }}
|
||||||
|
path: bin/packages/${{ matrix.arch }}/ndpid_openwrt_packages_ci/*.ipk
|
||||||
45
.github/workflows/build-rpm.yml
vendored
Normal file
45
.github/workflows/build-rpm.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
name: RPM Build
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# At the end of every day
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- tmp
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Ubuntu Prerequisites
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install fakeroot alien autoconf automake cmake libtool pkg-config gettext libjson-c-dev flex bison libpcap-dev zlib1g-dev libcurl4-openssl-dev libdbus-1-dev
|
||||||
|
|
||||||
|
- name: Build RPM package
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build-rpm -DBUILD_EXAMPLES=ON -DBUILD_NDPI=ON -DCMAKE_BUILD_TYPE=Release
|
||||||
|
cmake --build build-rpm --parallel
|
||||||
|
cd build-rpm
|
||||||
|
cpack -G RPM
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
- name: Convert/Install RPM package
|
||||||
|
run: |
|
||||||
|
fakeroot alien --scripts --to-deb --verbose ./build-rpm/nDPId-*.rpm
|
||||||
|
sudo dpkg -i ./ndpid_*.deb
|
||||||
|
|
||||||
|
- name: Upload RPM
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: nDPId-rpm-packages
|
||||||
|
path: build-rpm/*.rpm
|
||||||
409
.github/workflows/build.yml
vendored
Normal file
409
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
# At the end of every day
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- tmp
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: ${{ matrix.os }} ${{ matrix.compiler }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CMAKE_C_COMPILER: ${{ matrix.compiler }}
|
||||||
|
CMAKE_C_FLAGS: -Werror ${{ matrix.cflags }}
|
||||||
|
CMAKE_C_EXE_LINKER_FLAGS: ${{ matrix.ldflags }}
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS: ${{ matrix.ldflags }}
|
||||||
|
DYLD_LIBRARY_PATH: /usr/local/lib
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- compiler: "gcc"
|
||||||
|
os: "ubuntu-latest"
|
||||||
|
ndpi_build: "-DBUILD_NDPI=ON"
|
||||||
|
ndpid_examples: "-DBUILD_EXAMPLES=ON"
|
||||||
|
ndpid_rust_examples: "-DBUILD_RUST_EXAMPLES=ON"
|
||||||
|
ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF"
|
||||||
|
ndpid_zlib: "-DENABLE_ZLIB=ON"
|
||||||
|
ndpid_extras: "-DENABLE_CRYPTO=ON"
|
||||||
|
sanitizer: "-DENABLE_SANITIZER=OFF -DENABLE_SANITIZER_THREAD=OFF"
|
||||||
|
coverage: "-DENABLE_COVERAGE=OFF"
|
||||||
|
poll: "-DFORCE_POLL=OFF"
|
||||||
|
upload: true
|
||||||
|
upload_suffix: ""
|
||||||
|
ndpi_min_version: "5.0"
|
||||||
|
- compiler: "gcc"
|
||||||
|
os: "ubuntu-latest"
|
||||||
|
ndpi_build: "-DBUILD_NDPI=ON"
|
||||||
|
ndpid_examples: "-DBUILD_EXAMPLES=ON"
|
||||||
|
ndpid_rust_examples: ""
|
||||||
|
ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=ON"
|
||||||
|
ndpid_zlib: "-DENABLE_ZLIB=ON"
|
||||||
|
ndpid_extras: "-DENABLE_CRYPTO=ON -DNDPI_WITH_MAXMINDDB=ON -DNDPI_WITH_PCRE=ON -DENABLE_MEMORY_PROFILING=ON"
|
||||||
|
sanitizer: "-DENABLE_SANITIZER=OFF -DENABLE_SANITIZER_THREAD=OFF"
|
||||||
|
coverage: "-DENABLE_COVERAGE=OFF"
|
||||||
|
poll: "-DFORCE_POLL=OFF"
|
||||||
|
upload: true
|
||||||
|
upload_suffix: "-host-gcrypt"
|
||||||
|
ndpi_min_version: "5.0"
|
||||||
|
- compiler: "clang"
|
||||||
|
os: "ubuntu-latest"
|
||||||
|
ndpi_build: "-DBUILD_NDPI=ON"
|
||||||
|
ndpid_examples: "-DBUILD_EXAMPLES=ON"
|
||||||
|
ndpid_rust_examples: ""
|
||||||
|
ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF"
|
||||||
|
ndpid_zlib: "-DENABLE_ZLIB=OFF"
|
||||||
|
ndpid_extras: ""
|
||||||
|
sanitizer: "-DENABLE_SANITIZER=OFF -DENABLE_SANITIZER_THREAD=OFF"
|
||||||
|
coverage: "-DENABLE_COVERAGE=OFF"
|
||||||
|
poll: "-DFORCE_POLL=OFF"
|
||||||
|
upload: true
|
||||||
|
upload_suffix: "-no-zlib"
|
||||||
|
ndpi_min_version: "5.0"
|
||||||
|
- compiler: "gcc"
|
||||||
|
os: "ubuntu-latest"
|
||||||
|
ndpi_build: "-DBUILD_NDPI=ON"
|
||||||
|
ndpid_examples: "-DBUILD_EXAMPLES=ON"
|
||||||
|
ndpid_rust_examples: ""
|
||||||
|
ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF"
|
||||||
|
ndpid_zlib: "-DENABLE_ZLIB=ON"
|
||||||
|
ndpid_extras: ""
|
||||||
|
sanitizer: "-DENABLE_SANITIZER=ON"
|
||||||
|
coverage: "-DENABLE_COVERAGE=ON"
|
||||||
|
poll: "-DFORCE_POLL=ON"
|
||||||
|
upload: false
|
||||||
|
ndpi_min_version: "5.0"
|
||||||
|
- compiler: "clang"
|
||||||
|
os: "ubuntu-latest"
|
||||||
|
ndpi_build: "-DBUILD_NDPI=ON"
|
||||||
|
ndpid_examples: "-DBUILD_EXAMPLES=ON"
|
||||||
|
ndpid_rust_examples: ""
|
||||||
|
ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF"
|
||||||
|
ndpid_zlib: "-DENABLE_ZLIB=ON"
|
||||||
|
ndpid_extras: "-DENABLE_CRYPTO=ON"
|
||||||
|
sanitizer: "-DENABLE_SANITIZER=ON"
|
||||||
|
coverage: "-DENABLE_COVERAGE=OFF"
|
||||||
|
poll: "-DFORCE_POLL=OFF"
|
||||||
|
upload: false
|
||||||
|
ndpi_min_version: "5.0"
|
||||||
|
- compiler: "clang-12"
|
||||||
|
os: "ubuntu-22.04"
|
||||||
|
ndpi_build: "-DBUILD_NDPI=ON"
|
||||||
|
ndpid_examples: "-DBUILD_EXAMPLES=ON"
|
||||||
|
ndpid_rust_examples: ""
|
||||||
|
ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF"
|
||||||
|
ndpid_zlib: "-DENABLE_ZLIB=ON"
|
||||||
|
ndpid_extras: ""
|
||||||
|
sanitizer: "-DENABLE_SANITIZER_THREAD=ON"
|
||||||
|
coverage: "-DENABLE_COVERAGE=OFF"
|
||||||
|
poll:
|
||||||
|
upload: false
|
||||||
|
ndpi_min_version: "5.0"
|
||||||
|
- compiler: "gcc-10"
|
||||||
|
os: "ubuntu-22.04"
|
||||||
|
ndpi_build: "-DBUILD_NDPI=ON"
|
||||||
|
ndpid_examples: "-DBUILD_EXAMPLES=ON"
|
||||||
|
ndpid_rust_examples: ""
|
||||||
|
ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF"
|
||||||
|
ndpid_zlib: "-DENABLE_ZLIB=OFF"
|
||||||
|
ndpid_extras: ""
|
||||||
|
sanitizer: "-DENABLE_SANITIZER=ON"
|
||||||
|
coverage: "-DENABLE_COVERAGE=OFF"
|
||||||
|
poll: "-DFORCE_POLL=ON"
|
||||||
|
upload: false
|
||||||
|
ndpi_min_version: "5.0"
|
||||||
|
- compiler: "gcc-9"
|
||||||
|
os: "ubuntu-22.04"
|
||||||
|
ndpi_build: "-DBUILD_NDPI=ON"
|
||||||
|
ndpid_examples: "-DBUILD_EXAMPLES=ON"
|
||||||
|
ndpid_rust_examples: ""
|
||||||
|
ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF"
|
||||||
|
ndpid_zlib: "-DENABLE_ZLIB=ON"
|
||||||
|
ndpid_extras: ""
|
||||||
|
sanitizer: "-DENABLE_SANITIZER=ON"
|
||||||
|
coverage: "-DENABLE_COVERAGE=OFF"
|
||||||
|
poll: "-DFORCE_POLL=OFF"
|
||||||
|
upload: false
|
||||||
|
ndpi_min_version: "5.0"
|
||||||
|
- compiler: "cc"
|
||||||
|
os: "macOS-13"
|
||||||
|
ndpi_build: "-DBUILD_NDPI=OFF"
|
||||||
|
ndpid_examples: "-DBUILD_EXAMPLES=OFF"
|
||||||
|
ndpid_rust_examples: ""
|
||||||
|
ndpid_gcrypt: "-DNDPI_WITH_GCRYPT=OFF"
|
||||||
|
ndpid_zlib: "-DENABLE_ZLIB=ON"
|
||||||
|
ndpid_extras: ""
|
||||||
|
examples: "-DBUILD_EXAMPLES=OFF"
|
||||||
|
sanitizer: "-DENABLE_SANITIZER=OFF"
|
||||||
|
coverage: "-DENABLE_COVERAGE=OFF"
|
||||||
|
poll:
|
||||||
|
upload: false
|
||||||
|
ndpi_min_version: "5.0"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Print Matrix
|
||||||
|
run: |
|
||||||
|
echo '----------------------------------------'
|
||||||
|
echo '| OS.......: ${{ matrix.os }}'
|
||||||
|
echo '| CC.......: ${{ matrix.compiler }}'
|
||||||
|
echo "| CFLAGS...: $CMAKE_C_FLAGS"
|
||||||
|
echo "| LDFLAGS..: $CMAKE_C_EXE_LINKER_FLAGS"
|
||||||
|
echo '|---------------------------------------'
|
||||||
|
echo '| nDPI min.: ${{ matrix.ndpi_min_version }}'
|
||||||
|
echo '| GCRYPT...: ${{ matrix.ndpid_gcrypt }}'
|
||||||
|
echo '| ZLIB.....: ${{ matrix.ndpid_zlib }}'
|
||||||
|
echo '| Extras...: ${{ matrix.ndpid_extras }}'
|
||||||
|
echo '| ForcePoll: ${{ matrix.poll }}'
|
||||||
|
echo '|---------------------------------------'
|
||||||
|
echo '| SANITIZER: ${{ matrix.sanitizer }}'
|
||||||
|
echo '| COVERAGE.: ${{ matrix.coverage }}'
|
||||||
|
echo '|---------------------------------------'
|
||||||
|
echo '| UPLOAD...: ${{ matrix.upload }}'
|
||||||
|
echo '----------------------------------------'
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Install MacOS Prerequisites
|
||||||
|
if: startsWith(matrix.os, 'macOS')
|
||||||
|
run: |
|
||||||
|
brew install coreutils automake make unzip
|
||||||
|
wget 'https://www.tcpdump.org/release/libpcap-1.10.4.tar.gz'
|
||||||
|
tar -xzvf libpcap-1.10.4.tar.gz
|
||||||
|
cd libpcap-1.10.4
|
||||||
|
./configure && make install
|
||||||
|
cd ..
|
||||||
|
wget 'https://github.com/ntop/nDPI/archive/refs/heads/dev.zip' -O libndpi-dev.zip
|
||||||
|
unzip libndpi-dev.zip
|
||||||
|
cd nDPI-dev
|
||||||
|
./autogen.sh
|
||||||
|
./configure --prefix=/usr/local --with-only-libndpi && make install
|
||||||
|
- name: Fix kernel mmap rnd bits on Ubuntu
|
||||||
|
if: startsWith(matrix.os, 'ubuntu')
|
||||||
|
run: |
|
||||||
|
# Workaround for compatinility between latest kernel and sanitizer
|
||||||
|
# See https://github.com/actions/runner-images/issues/9491
|
||||||
|
sudo sysctl vm.mmap_rnd_bits=28
|
||||||
|
- name: Install Ubuntu Prerequisites
|
||||||
|
if: startsWith(matrix.os, 'ubuntu')
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install autoconf automake cmake libtool pkg-config gettext libjson-c-dev flex bison libpcap-dev zlib1g-dev libcurl4-openssl-dev libdbus-1-dev
|
||||||
|
sudo apt-get install ${{ matrix.compiler }} lcov iproute2
|
||||||
|
- name: Install Ubuntu Prerequisites (Rust/Cargo)
|
||||||
|
if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.ndpid_rust_examples, '-DBUILD_RUST_EXAMPLES=ON')
|
||||||
|
run: |
|
||||||
|
sudo apt-get install cargo
|
||||||
|
- name: Install Ubuntu Prerequisites (libgcrypt)
|
||||||
|
if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=ON')
|
||||||
|
run: |
|
||||||
|
sudo apt-get install libgcrypt20-dev
|
||||||
|
- name: Install Ubuntu Prerequisites (zlib)
|
||||||
|
if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.ndpid_zlib, '-DENABLE_ZLIB=ON')
|
||||||
|
run: |
|
||||||
|
sudo apt-get install zlib1g-dev
|
||||||
|
- name: Install Ubuntu Prerequisites (libmaxminddb, libpcre2)
|
||||||
|
if: startsWith(matrix.ndpid_extras, '-D')
|
||||||
|
run: |
|
||||||
|
sudo apt-get install libmaxminddb-dev libpcre2-dev
|
||||||
|
- name: Install Ubuntu Prerequisites (libnl-genl-3-dev)
|
||||||
|
if: startsWith(matrix.ndpi_build, '-DBUILD_NDPI=ON') && startsWith(matrix.coverage, '-DENABLE_COVERAGE=OFF') && startsWith(matrix.sanitizer, '-DENABLE_SANITIZER=ON') && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=OFF') && startsWith(matrix.ndpid_zlib, '-DENABLE_ZLIB=ON')
|
||||||
|
run: |
|
||||||
|
sudo apt-get install libnl-genl-3-dev
|
||||||
|
- name: Checking Network Buffer Size
|
||||||
|
run: |
|
||||||
|
C_VAL=$(cat config.h | sed -n 's/^#define\s\+NETWORK_BUFFER_MAX_SIZE\s\+\([0-9]\+\).*$/\1/gp')
|
||||||
|
PY_VAL=$(cat dependencies/nDPIsrvd.py | sed -n 's/^NETWORK_BUFFER_MAX_SIZE = \([0-9]\+\).*$/\1/gp')
|
||||||
|
test ${C_VAL} = ${PY_VAL}
|
||||||
|
- name: Configure nDPId
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build -Werror=dev -Werror=deprecated -DCMAKE_C_COMPILER="$CMAKE_C_COMPILER" -DCMAKE_C_FLAGS="$CMAKE_C_FLAGS" -DCMAKE_MODULE_LINKER_FLAGS="$CMAKE_MODULE_LINKER_FLAGS" -DCMAKE_C_EXE_LINKER_FLAGS="$CMAKE_C_EXE_LINKER_FLAGS" \
|
||||||
|
-DENABLE_DBUS=ON -DENABLE_CURL=ON -DENABLE_SYSTEMD=ON \
|
||||||
|
${{ matrix.poll }} ${{ matrix.coverage }} ${{ matrix.sanitizer }} ${{ matrix.ndpi_build }} \
|
||||||
|
${{ matrix.ndpid_examples }} ${{ matrix.ndpid_rust_examples }} ${{ matrix.ndpid_zlib }} ${{ matrix.ndpid_gcrypt }} ${{ matrix.ndpid_extras }}
|
||||||
|
- name: Build nDPId
|
||||||
|
run: |
|
||||||
|
cmake --build build --verbose
|
||||||
|
- name: Build single nDPId/nDPIsrvd executables (invoke CC directly - dynamic nDPI lib)
|
||||||
|
if: startsWith(matrix.ndpi_build, '-DBUILD_NDPI=OFF') && startsWith(matrix.coverage, '-DENABLE_COVERAGE=OFF') && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=OFF')
|
||||||
|
run: |
|
||||||
|
pkg-config --cflags --libs libndpi
|
||||||
|
cc -Wall -Wextra -std=gnu99 \
|
||||||
|
${{ matrix.poll }} -DENABLE_MEMORY_PROFILING=1 \
|
||||||
|
nDPId.c nio.c utils.c \
|
||||||
|
$(pkg-config --cflags libndpi) -I. -I./dependencies -I./dependencies/jsmn -I./dependencies/uthash/include \
|
||||||
|
-o /tmp/a.out \
|
||||||
|
-lpcap $(pkg-config --libs libndpi) -pthread -lm
|
||||||
|
cc -Wall -Wextra -std=gnu99 \
|
||||||
|
${{ matrix.poll }} -DENABLE_MEMORY_PROFILING=1 \
|
||||||
|
nDPIsrvd.c nio.c utils.c \
|
||||||
|
-I. -I./dependencies -I./dependencies/jsmn -I./dependencies/uthash/include \
|
||||||
|
-o /tmp/a.out
|
||||||
|
- name: Build single nDPId/nDPIsrvd executables (invoke CC directly - static nDPI lib)
|
||||||
|
if: startsWith(matrix.ndpi_build, '-DBUILD_NDPI=ON') && startsWith(matrix.coverage, '-DENABLE_COVERAGE=OFF') && startsWith(matrix.sanitizer, '-DENABLE_SANITIZER=ON') && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=OFF') && startsWith(matrix.ndpid_zlib, '-DENABLE_ZLIB=ON')
|
||||||
|
run: |
|
||||||
|
cc -Wall -Wextra -std=gnu99 ${{ matrix.poll }} -DENABLE_ZLIB=1 -DENABLE_MEMORY_PROFILING=1 \
|
||||||
|
-fsanitize=address -fsanitize=undefined -fno-sanitize=alignment -fsanitize=enum -fsanitize=leak \
|
||||||
|
nDPId.c nio.c utils.c \
|
||||||
|
-I./build/libnDPI/include/ndpi -I. -I./dependencies -I./dependencies/jsmn -I./dependencies/uthash/include \
|
||||||
|
-o /tmp/a.out \
|
||||||
|
-lpcap ./build/libnDPI/lib/libndpi.a -pthread -lm -lz
|
||||||
|
- name: Test EXEC
|
||||||
|
run: |
|
||||||
|
./build/nDPId-test
|
||||||
|
./build/nDPId -h || test $? -eq 1
|
||||||
|
./build/nDPIsrvd -h || test $? -eq 1
|
||||||
|
- name: Test DIFF
|
||||||
|
if: startsWith(matrix.os, 'macOS') == false && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=OFF')
|
||||||
|
run: |
|
||||||
|
./test/run_tests.sh ./libnDPI ./build/nDPId-test
|
||||||
|
./test/run_config_tests.sh ./libnDPI ./build/nDPId-test
|
||||||
|
- name: Daemon
|
||||||
|
if: startsWith(matrix.compiler, 'gcc') || endsWith(matrix.compiler, 'clang')
|
||||||
|
run: |
|
||||||
|
make -C ./build daemon VERBOSE=1
|
||||||
|
make -C ./build daemon VERBOSE=1
|
||||||
|
- name: Coverage
|
||||||
|
if: startsWith(matrix.coverage, '-DENABLE_COVERAGE=ON')
|
||||||
|
run: |
|
||||||
|
make -C ./build coverage
|
||||||
|
- name: Dist
|
||||||
|
if: startsWith(matrix.os, 'macOS') == false && matrix.upload == false
|
||||||
|
run: |
|
||||||
|
make -C ./build dist
|
||||||
|
RAND_ID=$(( ( RANDOM ) + 1 ))
|
||||||
|
mkdir "nDPId-dist-${RAND_ID}"
|
||||||
|
cd "nDPId-dist-${RAND_ID}"
|
||||||
|
tar -xjf ../nDPId-*.tar.bz2
|
||||||
|
cd ./nDPId-*
|
||||||
|
cmake -S . -B ./build \
|
||||||
|
-DENABLE_DBUS=ON -DENABLE_CURL=ON -DENABLE_SYSTEMD=ON \
|
||||||
|
${{ matrix.poll }} ${{ matrix.coverage }} ${{ matrix.sanitizer }} ${{ matrix.ndpi_build }} \
|
||||||
|
${{ matrix.ndpid_examples }} ${{ matrix.ndpid_rust_examples }} ${{ matrix.ndpid_zlib }} ${{ matrix.ndpid_gcrypt }} ${{ matrix.ndpid_extras }}
|
||||||
|
cd ../..
|
||||||
|
rm -rf "nDPId-dist-${RAND_ID}"
|
||||||
|
- name: CPack DEB
|
||||||
|
if: startsWith(matrix.os, 'macOS') == false
|
||||||
|
run: |
|
||||||
|
cd ./build && cpack -G DEB && \
|
||||||
|
sudo dpkg -i nDPId-*.deb && \
|
||||||
|
sudo apt purge ndpid && \
|
||||||
|
sudo dpkg -i nDPId-*.deb && cd ..
|
||||||
|
- name: Upload DEB
|
||||||
|
if: startsWith(matrix.os, 'macOS') == false && matrix.upload
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: nDPId-debian-packages_${{ matrix.compiler }}${{ matrix.upload_suffix }}
|
||||||
|
path: build/*.deb
|
||||||
|
- name: Test systemd
|
||||||
|
if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.compiler, 'gcc')
|
||||||
|
run: |
|
||||||
|
ip -c address
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable ndpid@lo
|
||||||
|
sudo systemctl start ndpid@lo
|
||||||
|
SYSTEMCTL_RET=3; while (( $SYSTEMCTL_RET == 3 )); do systemctl is-active ndpid@lo.service; SYSTEMCTL_RET=$?; sleep 1; done
|
||||||
|
sudo systemctl status ndpisrvd.service ndpid@lo.service
|
||||||
|
sudo systemctl show ndpisrvd.service ndpid@lo.service -p SubState,ActiveState
|
||||||
|
sudo dpkg -i ./build/nDPId-*.deb
|
||||||
|
sudo systemctl status ndpisrvd.service ndpid@lo.service
|
||||||
|
sudo systemctl show ndpisrvd.service ndpid@lo.service -p SubState,ActiveState
|
||||||
|
sudo systemctl stop ndpisrvd.service
|
||||||
|
journalctl --no-tail --no-pager -u ndpisrvd.service -u ndpid@lo.service
|
||||||
|
- name: Build PF_RING and nDPId (invoke CC directly - dynamic nDPI lib)
|
||||||
|
if: startsWith(matrix.ndpi_build, '-DBUILD_NDPI=ON') && startsWith(matrix.coverage, '-DENABLE_COVERAGE=OFF') && startsWith(matrix.sanitizer, '-DENABLE_SANITIZER=ON') && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=OFF') && startsWith(matrix.ndpid_zlib, '-DENABLE_ZLIB=ON')
|
||||||
|
run: |
|
||||||
|
git clone --depth=1 https://github.com/ntop/PF_RING.git
|
||||||
|
cd PF_RING/userland && ./configure && make && sudo make install prefix=/usr
|
||||||
|
cd ../..
|
||||||
|
cc -Wall -Wextra -std=gnu99 ${{ matrix.poll }} -DENABLE_PFRING=1 -DENABLE_ZLIB=1 -DENABLE_MEMORY_PROFILING=1 \
|
||||||
|
-fsanitize=address -fsanitize=undefined -fno-sanitize=alignment -fsanitize=enum -fsanitize=leak \
|
||||||
|
nDPId.c npfring.c nio.c utils.c \
|
||||||
|
-I. -I./dependencies -I./dependencies/jsmn -I./dependencies/uthash/include \
|
||||||
|
-I./build/libnDPI/include/ndpi \
|
||||||
|
-I./PF_RING/userland/lib -I./PF_RING/kernel \
|
||||||
|
-o /tmp/a.out \
|
||||||
|
-ldl /usr/lib/libpfring.a -lpcap ./build/libnDPI/lib/libndpi.a -pthread -lm -lz
|
||||||
|
- name: Build against libnDPI-${{ matrix.ndpi_min_version }}
|
||||||
|
if: startsWith(matrix.os, 'ubuntu')
|
||||||
|
run: |
|
||||||
|
mkdir build-local-ndpi && cd build-local-ndpi
|
||||||
|
WGET_RET=0
|
||||||
|
wget 'https://github.com/ntop/nDPI/archive/refs/tags/${{ matrix.ndpi_min_version }}.tar.gz' || { WGET_RET=$?; true; }
|
||||||
|
echo "wget returned: ${WGET_RET}"
|
||||||
|
test $WGET_RET -ne 8 && { \
|
||||||
|
tar -xzvf ${{ matrix.ndpi_min_version }}.tar.gz; }
|
||||||
|
test $WGET_RET -ne 8 || { \
|
||||||
|
echo "::warning file=nDPId.c::New libnDPI release required to build against release tarball, falling back to dev branch."; \
|
||||||
|
wget 'http://github.com/ntop/nDPI/archive/refs/heads/dev.tar.gz'; \
|
||||||
|
WGET_RET=$?; \
|
||||||
|
tar -xzvf dev.tar.gz; \
|
||||||
|
mv -v 'nDPI-dev' 'nDPI-${{ matrix.ndpi_min_version }}'; }
|
||||||
|
test $WGET_RET -ne 0 || { cd nDPI-${{ matrix.ndpi_min_version }}; \
|
||||||
|
NDPI_CONFIGURE_ARGS=''; \
|
||||||
|
test 'x${{ matrix.ndpid_gcrypt }}' != 'x-DNDPI_WITH_GCRYPT=ON' || NDPI_CONFIGURE_ARGS="$NDPI_CONFIGURE_ARGS --with-local-libgcrypt"; \
|
||||||
|
test 'x${{ matrix.sanitizer }}' != 'x-DENABLE_SANITIZER=ON' || NDPI_CONFIGURE_ARGS="$NDPI_CONFIGURE_ARGS --with-sanitizer"; \
|
||||||
|
echo "Configure arguments: '$NDPI_CONFIGURE_ARGS'"; \
|
||||||
|
./autogen.sh; \
|
||||||
|
./configure --prefix=/usr --with-only-libndpi $NDPI_CONFIGURE_ARGS CC="${{ matrix.compiler }}" CXX=false \
|
||||||
|
CFLAGS="$CMAKE_C_FLAGS" && make && sudo make install; cd ..; }
|
||||||
|
ls -alhR /usr/include/ndpi
|
||||||
|
cd ..
|
||||||
|
test $WGET_RET -ne 0 || { echo "Running CMake.. (pkgconfig)"; \
|
||||||
|
cmake -S . -B ./build-local-pkgconfig \
|
||||||
|
-DCMAKE_C_COMPILER="$CMAKE_C_COMPILER" -DCMAKE_C_FLAGS="$CMAKE_C_FLAGS" \
|
||||||
|
-DCMAKE_C_EXE_LINKER_FLAGS="$CMAKE_C_EXE_LINKER_FLAGS" \
|
||||||
|
-DBUILD_NDPI=OFF -DBUILD_EXAMPLES=ON \
|
||||||
|
-DENABLE_DBUS=ON -DENABLE_CURL=ON -DENABLE_SYSTEMD=ON \
|
||||||
|
${{ matrix.poll }} ${{ matrix.coverage }} \
|
||||||
|
${{ matrix.sanitizer }} ${{ matrix.ndpid_examples }} ${{ matrix.ndpid_rust_examples }}; }
|
||||||
|
test $WGET_RET -ne 0 || { echo "Running Make.. (pkgconfig)"; \
|
||||||
|
cmake --build ./build-local-pkgconfig --verbose; }
|
||||||
|
test $WGET_RET -ne 0 || { echo "Testing Executable.. (pkgconfig)"; \
|
||||||
|
./build-local-pkgconfig/nDPId-test; \
|
||||||
|
./build-local-pkgconfig/nDPId -h || test $? -eq 1; \
|
||||||
|
./build-local-pkgconfig/nDPIsrvd -h || test $? -eq 1; }
|
||||||
|
test $WGET_RET -ne 0 || { echo "Running CMake.. (static)"; \
|
||||||
|
cmake -S . -B ./build-local-static \
|
||||||
|
-DCMAKE_C_COMPILER="$CMAKE_C_COMPILER" -DCMAKE_C_FLAGS="$CMAKE_C_FLAGS" \
|
||||||
|
-DCMAKE_C_EXE_LINKER_FLAGS="$CMAKE_C_EXE_LINKER_FLAGS" \
|
||||||
|
-DBUILD_NDPI=OFF -DBUILD_EXAMPLES=ON \
|
||||||
|
-DENABLE_DBUS=ON -DENABLE_CURL=ON -DENABLE_SYSTEMD=ON \
|
||||||
|
-DNDPI_NO_PKGCONFIG=ON -DSTATIC_LIBNDPI_INSTALLDIR=/usr \
|
||||||
|
${{ matrix.poll }} ${{ matrix.coverage }} ${{ matrix.ndpid_gcrypt }} \
|
||||||
|
${{ matrix.sanitizer }} ${{ matrix.ndpid_examples }} ${{ matrix.ndpid_rust_examples }}; }
|
||||||
|
test $WGET_RET -ne 0 || { echo "Running Make.. (static)"; \
|
||||||
|
cmake --build ./build-local-static --verbose; }
|
||||||
|
test $WGET_RET -ne 0 || { echo "Testing Executable.. (static)"; \
|
||||||
|
./build-local-static/nDPId-test; \
|
||||||
|
./build-local-static/nDPId -h || test $? -eq 1; \
|
||||||
|
./build-local-static/nDPIsrvd -h || test $? -eq 1; }
|
||||||
|
test $WGET_RET -ne 0 || test ! -d ./PF_RING || { echo "Running CMake.. (PF_RING)"; \
|
||||||
|
cmake -S . -B ./build-local-pfring \
|
||||||
|
-DCMAKE_C_COMPILER="$CMAKE_C_COMPILER" -DCMAKE_C_FLAGS="$CMAKE_C_FLAGS" \
|
||||||
|
-DCMAKE_C_EXE_LINKER_FLAGS="$CMAKE_C_EXE_LINKER_FLAGS" \
|
||||||
|
-DBUILD_NDPI=OFF -DBUILD_EXAMPLES=ON -DENABLE_PFRING=ON \
|
||||||
|
-DENABLE_DBUS=ON -DENABLE_CURL=ON -DENABLE_SYSTEMD=ON \
|
||||||
|
-DNDPI_NO_PKGCONFIG=ON -DSTATIC_LIBNDPI_INSTALLDIR=/usr \
|
||||||
|
-DPFRING_LINK_STATIC=OFF \
|
||||||
|
-DPFRING_INSTALLDIR=/usr -DPFRING_KERNEL_INC="$(realpath ./PF_RING/kernel)" \
|
||||||
|
${{ matrix.poll }} ${{ matrix.coverage }} ${{ matrix.ndpid_gcrypt }} \
|
||||||
|
${{ matrix.sanitizer }} ${{ matrix.ndpid_examples }} ${{ matrix.ndpid_rust_examples }}; }
|
||||||
|
test $WGET_RET -ne 0 || test ! -d ./PF_RING || { echo "Running Make.. (PF_RING)"; \
|
||||||
|
cmake --build ./build-local-pfring --verbose; }
|
||||||
|
test $WGET_RET -ne 0 || test ! -d ./PF_RING || { echo "Testing Executable.. (PF_RING)"; \
|
||||||
|
./build-local-pfring/nDPId-test; \
|
||||||
|
./build-local-pfring/nDPId -h || test $? -eq 1; \
|
||||||
|
./build-local-pfring/nDPIsrvd -h || test $? -eq 1; }
|
||||||
|
test $WGET_RET -eq 0 -o $WGET_RET -eq 8
|
||||||
66
.github/workflows/sonarcloud.yml
vendored
Normal file
66
.github/workflows/sonarcloud.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- tmp
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
|
||||||
|
name: Sonarcloud Scan
|
||||||
|
jobs:
|
||||||
|
sonarcloud:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Set up Python 3.8 for gcovr
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: 3.8
|
||||||
|
- name: install gcovr 5.0
|
||||||
|
run: |
|
||||||
|
pip install gcovr==5.0 # 5.1 is not supported
|
||||||
|
- name: Install sonar-scanner and build-wrapper
|
||||||
|
uses: SonarSource/sonarcloud-github-c-cpp@v3.2.0
|
||||||
|
- name: Install Prerequisites
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install autoconf automake cmake lcov \
|
||||||
|
libtool pkg-config gettext \
|
||||||
|
libjson-c-dev flex bison \
|
||||||
|
libcurl4-openssl-dev libpcap-dev zlib1g-dev
|
||||||
|
- name: Run build-wrapper
|
||||||
|
run: |
|
||||||
|
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} ./scripts/build-sonarcloud.sh
|
||||||
|
- name: Run tests
|
||||||
|
run: |
|
||||||
|
for file in $(ls libnDPI/tests/cfgs/*/pcap/*.pcap libnDPI/tests/cfgs/*/pcap/*.pcapng libnDPI/tests/cfgs/*/pcap/*.cap); do \
|
||||||
|
echo -n "${file} "; \
|
||||||
|
cd ./build-sonarcloud; \
|
||||||
|
./nDPId-test "../${file}" >/dev/null 2>/dev/null; \
|
||||||
|
cd ..; \
|
||||||
|
echo "[ok]"; \
|
||||||
|
done
|
||||||
|
mkdir -p gcov_report
|
||||||
|
cd gcov_report
|
||||||
|
gcov ../build-sonarcloud/CMakeFiles/nDPId-test.dir/nDPId-test.c.o
|
||||||
|
cd ..
|
||||||
|
- name: Run sonar-scanner
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
run: |
|
||||||
|
sonar-scanner \
|
||||||
|
--define sonar.projectName=nDPId \
|
||||||
|
--define sonar.projectVersion=1.7 \
|
||||||
|
--define sonar.sourceEncoding=UTF-8 \
|
||||||
|
--define sonar.branch.name=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} \
|
||||||
|
--define sonar.organization=lnslbrty \
|
||||||
|
--define sonar.projectKey=lnslbrty_nDPId \
|
||||||
|
--define sonar.python.version=3.8 \
|
||||||
|
--define sonar.cfamily.compile-commands=${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json \
|
||||||
|
--define sonar.cfamily.gcov.reportsPath=gcov_report \
|
||||||
|
--define sonar.exclusions=build-sonarcloud/**,libnDPI/**,test/results/**,dependencies/jsmn/**,dependencies/uthash/**,examples/js-rt-analyzer-frontend/**,examples/js-rt-analyzer/**,examples/c-collectd/www/**,examples/py-flow-dashboard/assets/**
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -4,3 +4,9 @@ __pycache__
|
|||||||
|
|
||||||
# go related
|
# go related
|
||||||
*.sum
|
*.sum
|
||||||
|
|
||||||
|
# lockfiles generated by some shell scripts
|
||||||
|
*.lock
|
||||||
|
|
||||||
|
# building folder
|
||||||
|
build
|
||||||
|
|||||||
135
.gitlab-ci.yml
Normal file
135
.gitlab-ci.yml
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
image: debian:stable
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- build_and_test
|
||||||
|
|
||||||
|
variables:
|
||||||
|
GIT_CLONE_PATH: '$CI_BUILDS_DIR/$CI_JOB_ID/$CI_PROJECT_NAME'
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- export DEBIAN_FRONTEND=noninteractive
|
||||||
|
- apt-get update -qq
|
||||||
|
- >
|
||||||
|
apt-get install -y -qq \
|
||||||
|
coreutils sudo \
|
||||||
|
build-essential make cmake binutils gcc clang autoconf automake \
|
||||||
|
libtool pkg-config git wget unzip \
|
||||||
|
libpcap-dev libgpg-error-dev libjson-c-dev zlib1g-dev \
|
||||||
|
netcat-openbsd python3 python3-jsonschema tree lcov iproute2
|
||||||
|
|
||||||
|
after_script:
|
||||||
|
- test -r /tmp/nDPIsrvd.log && cat /tmp/nDPIsrvd.log
|
||||||
|
- test -r /tmp/nDPId.log && cat /tmp/nDPId.log
|
||||||
|
|
||||||
|
build_and_test_static_libndpi_tsan:
|
||||||
|
script:
|
||||||
|
# test for NETWORK_BUFFER_MAX_SIZE C and Python value equality
|
||||||
|
- C_VAL=$(cat config.h | sed -n 's/^#define\s\+NETWORK_BUFFER_MAX_SIZE\s\+\([0-9]\+\).*$/\1/gp')
|
||||||
|
- PY_VAL=$(cat dependencies/nDPIsrvd.py | sed -n 's/^NETWORK_BUFFER_MAX_SIZE = \([0-9]\+\).*$/\1/gp')
|
||||||
|
- test ${C_VAL} = ${PY_VAL}
|
||||||
|
# test for nDPId_PACKETS_PLEN_MAX C and Python value equality
|
||||||
|
- C_VAL=$(cat config.h | sed -n 's/^#define\s\+nDPId_PACKETS_PLEN_MAX\s\+\([0-9]\+\).*$/\1/gp')
|
||||||
|
- PY_VAL=$(cat dependencies/nDPIsrvd.py | sed -n 's/^nDPId_PACKETS_PLEN_MAX = \([0-9]\+\).*$/\1/gp')
|
||||||
|
- test ${C_VAL} = ${PY_VAL}
|
||||||
|
# static linked build
|
||||||
|
- mkdir build-clang-tsan
|
||||||
|
- cd build-clang-tsan
|
||||||
|
- env CMAKE_C_FLAGS='-Werror' CMAKE_C_COMPILER='clang' cmake .. -DBUILD_EXAMPLES=ON -DBUILD_NDPI=ON -DBUILD_NDPI_FORCE_GIT_UPDATE=ON -DENABLE_SANITIZER_THREAD=ON -DENABLE_ZLIB=ON
|
||||||
|
- make clean-libnDPI
|
||||||
|
- make libnDPI
|
||||||
|
- tree libnDPI
|
||||||
|
- make install VERBOSE=1 DESTDIR="$(realpath ../_install)"
|
||||||
|
- cd ..
|
||||||
|
- ./_install/usr/local/bin/nDPId-test
|
||||||
|
- ./test/run_tests.sh ./libnDPI ./_install/usr/local/bin/nDPId-test
|
||||||
|
artifacts:
|
||||||
|
expire_in: 1 week
|
||||||
|
paths:
|
||||||
|
- _install/
|
||||||
|
stage: build_and_test
|
||||||
|
|
||||||
|
build_and_test_static_libndpi:
|
||||||
|
script:
|
||||||
|
- mkdir build-cmake-submodule
|
||||||
|
- cd build-cmake-submodule
|
||||||
|
- env CMAKE_C_FLAGS='-Werror' cmake .. -DENABLE_SYSTEMD=ON -DBUILD_EXAMPLES=ON -DBUILD_NDPI=ON -DBUILD_NDPI_FORCE_GIT_UPDATE=ON -DENABLE_ZLIB=ON
|
||||||
|
- make clean-libnDPI
|
||||||
|
- make libnDPI
|
||||||
|
- tree libnDPI
|
||||||
|
- make install VERBOSE=1 DESTDIR="$(realpath ../_install)"
|
||||||
|
- cpack -G DEB
|
||||||
|
- sudo dpkg -i nDPId-*.deb
|
||||||
|
- cd ..
|
||||||
|
- test -x /bin/systemctl && sudo systemctl daemon-reload
|
||||||
|
- test -x /bin/systemctl && sudo systemctl enable ndpid@lo
|
||||||
|
- test -x /bin/systemctl && sudo systemctl start ndpid@lo
|
||||||
|
- test -x /bin/systemctl && sudo systemctl status ndpisrvd.service ndpid@lo.service
|
||||||
|
- test -x /bin/systemctl && sudo systemctl stop ndpid@lo
|
||||||
|
- ./build-cmake-submodule/nDPId-test
|
||||||
|
- ./test/run_tests.sh ./libnDPI ./build-cmake-submodule/nDPId-test
|
||||||
|
- >
|
||||||
|
if ldd ./build-cmake-submodule/nDPId | grep -qoEi libndpi; then \
|
||||||
|
echo 'nDPId linked against a static libnDPI should not contain a shared linked libnDPI.' >&2; false; fi
|
||||||
|
- cc -Wall -Wextra -std=gnu99 nDPId.c nio.c utils.c -I./build-cmake-submodule/libnDPI/include/ndpi -I. -I./dependencies -I./dependencies/jsmn -I./dependencies/uthash/include -o /tmp/a.out -lpcap ./build-cmake-submodule/libnDPI/lib/libndpi.a -pthread -lm -lz
|
||||||
|
artifacts:
|
||||||
|
expire_in: 1 week
|
||||||
|
paths:
|
||||||
|
- build-cmake-submodule/*.deb
|
||||||
|
- _install/
|
||||||
|
stage: build_and_test
|
||||||
|
|
||||||
|
build_and_test_static_libndpi_coverage:
|
||||||
|
script:
|
||||||
|
- mkdir build-cmake-submodule
|
||||||
|
- cd build-cmake-submodule
|
||||||
|
- env CMAKE_C_FLAGS='-Werror' cmake .. -DENABLE_SYSTEMD=ON -DENABLE_COVERAGE=ON -DBUILD_EXAMPLES=ON -DBUILD_NDPI=ON -DBUILD_NDPI_FORCE_GIT_UPDATE=ON -DENABLE_SANITIZER=ON -DENABLE_ZLIB=ON
|
||||||
|
- make clean-libnDPI
|
||||||
|
- make libnDPI
|
||||||
|
- tree libnDPI
|
||||||
|
- make install VERBOSE=1 DESTDIR="$(realpath ../_install)"
|
||||||
|
- cd ..
|
||||||
|
- ./build-cmake-submodule/nDPId-test
|
||||||
|
- ./test/run_tests.sh ./libnDPI ./build-cmake-submodule/nDPId-test
|
||||||
|
# generate coverage report
|
||||||
|
- make -C ./build-cmake-submodule coverage || true
|
||||||
|
- >
|
||||||
|
if ldd build/nDPId | grep -qoEi libndpi; then \
|
||||||
|
echo 'nDPId linked against a static libnDPI should not contain a shared linked libnDPI.' >&2; false; fi
|
||||||
|
artifacts:
|
||||||
|
expire_in: 1 week
|
||||||
|
paths:
|
||||||
|
- build-cmake-submodule/coverage_report
|
||||||
|
- _install/
|
||||||
|
stage: build_and_test
|
||||||
|
|
||||||
|
build_dynamic_libndpi:
|
||||||
|
script:
|
||||||
|
# pkg-config dynamic linked build
|
||||||
|
- git clone https://github.com/ntop/nDPI.git
|
||||||
|
- cd nDPI
|
||||||
|
- ./autogen.sh
|
||||||
|
- ./configure --prefix="$(realpath ../_install)" --enable-option-checking=fatal
|
||||||
|
- make install V=s
|
||||||
|
- cd ..
|
||||||
|
- tree ./_install
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- export CMAKE_PREFIX_PATH="$(realpath ../_install)"
|
||||||
|
- env CMAKE_C_FLAGS='-Werror' cmake .. -DBUILD_EXAMPLES=ON -DENABLE_SANITIZER=ON -DENABLE_MEMORY_PROFILING=ON -DENABLE_ZLIB=ON
|
||||||
|
- make all VERBOSE=1
|
||||||
|
- make install VERBOSE=1 DESTDIR="$(realpath ../_install)"
|
||||||
|
- cd ..
|
||||||
|
- tree ./_install
|
||||||
|
- ./build/nDPId-test
|
||||||
|
- ./build/nDPId -h || test $? -eq 1
|
||||||
|
- ./build/nDPIsrvd -h || test $? -eq 1
|
||||||
|
# dameon start/stop test
|
||||||
|
- NUSER=nobody make -C ./build daemon VERBOSE=1
|
||||||
|
- NUSER=nobody make -C ./build daemon VERBOSE=1
|
||||||
|
# make dist
|
||||||
|
- make -C ./build dist
|
||||||
|
artifacts:
|
||||||
|
expire_in: 1 week
|
||||||
|
paths:
|
||||||
|
- _install/
|
||||||
|
stage: build_and_test
|
||||||
9
.gitmodules
vendored
9
.gitmodules
vendored
@@ -3,3 +3,12 @@
|
|||||||
url = https://github.com/ntop/nDPI
|
url = https://github.com/ntop/nDPI
|
||||||
branch = dev
|
branch = dev
|
||||||
update = rebase
|
update = rebase
|
||||||
|
[submodule "examples/js-rt-analyzer"]
|
||||||
|
path = examples/js-rt-analyzer
|
||||||
|
url = https://gitlab.com/verzulli/ndpid-rt-analyzer.git
|
||||||
|
[submodule "examples/js-rt-analyzer-frontend"]
|
||||||
|
path = examples/js-rt-analyzer-frontend
|
||||||
|
url = https://gitlab.com/verzulli/ndpid-rt-analyzer-frontend.git
|
||||||
|
[submodule "examples/cxx-graph"]
|
||||||
|
path = examples/cxx-graph
|
||||||
|
url = https://github.com/utoni/nDPId-Graph.git
|
||||||
|
|||||||
15
.travis.yml
15
.travis.yml
@@ -1,15 +0,0 @@
|
|||||||
language: c
|
|
||||||
before_install:
|
|
||||||
- sudo apt-get -qq update
|
|
||||||
- sudo apt-get install -y build-essential make binutils gcc autoconf automake libtool pkg-config git libpcap-dev libgcrypt-dev libgpg-error-dev libjson-c-dev netcat-openbsd python3 python3-jsonschema
|
|
||||||
script:
|
|
||||||
# static linked build
|
|
||||||
- mkdir build-cmake-submodule && cd build-cmake-submodule &&
|
|
||||||
cmake .. -DBUILD_EXAMPLES=ON -DBUILD_NDPI=ON -DENABLE_SANITIZER=ON && make && cd ..
|
|
||||||
- ./test/run_tests.sh ./libnDPI ./build-cmake-submodule/nDPId-test
|
|
||||||
# pkg-config dynamic linked build
|
|
||||||
- mkdir build && cd build &&
|
|
||||||
PKG_CONFIG_PATH="$(realpath ../build-cmake-submodule/libnDPI/lib/pkgconfig)"
|
|
||||||
cmake .. -DBUILD_EXAMPLES=ON -DENABLE_SANITIZER=ON -DENABLE_MEMORY_PROFILING=ON && make && cd ..
|
|
||||||
- ./build/nDPId-test || test $? -eq 1
|
|
||||||
- ./build/nDPId -h || test $? -eq 1
|
|
||||||
83
CHANGELOG.md
Normal file
83
CHANGELOG.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# CHANGELOG
|
||||||
|
|
||||||
|
#### nDPId 1.7 (Oct 2024)
|
||||||
|
|
||||||
|
- Read and parse configuration files for nDPId (+ libnDPI) and nDPIsrvd
|
||||||
|
- Added loading risk domains from a file (`-R`, thanks to @UnveilTech)
|
||||||
|
- Added Filebeat configuration file
|
||||||
|
- Improved hostname handling; will now always be part of `analyse`/`end`/`idle` events (if dissected)
|
||||||
|
- Improved Documentation (INSTALL / Schema)
|
||||||
|
- Added PF\_RING support
|
||||||
|
- Improved nDPIsrvd-analyse to write global stats to a CSV
|
||||||
|
- Added global (heap) memory stats for daemon status events (if enabled)
|
||||||
|
- Fixed IPv6 address/netmask retrieval on some systems
|
||||||
|
- Improved nDPIsrvd-collect; gauges and counters are now handled the right way
|
||||||
|
- Added nDPId Grafana dashboard
|
||||||
|
- Fixed `detection-update` event bug; was thrown even if nothing changed
|
||||||
|
- Fixed `not-detected` event spam if detection not completed (in some rare cases)
|
||||||
|
- Improved InfluxDB push daemon (severity parsing / gauge handling)
|
||||||
|
- Improved zLib compression
|
||||||
|
- Fixed nDPIsrvd-collectd missing escape character
|
||||||
|
|
||||||
|
#### nDPId 1.6 (Nov 2023)
|
||||||
|
|
||||||
|
- Added Event I/O abstraction layer (supporting only poll/epoll by now)
|
||||||
|
- Support for OSX and *BSD systems
|
||||||
|
- Added proper DLT_RAW dissection for IPv4 and IPv6
|
||||||
|
- Improved TCP timeout handling if FIN/RST seen which caused Midstream TCP flows when there shouldn't be any
|
||||||
|
- Fixed a crash if `nDPId -o value=''` was used
|
||||||
|
- Added OpenWrt packaging
|
||||||
|
- Added new flow event "analyse" used to give some statistical information about active flows
|
||||||
|
- Added new analyse event daemon which generates CSV files from such events
|
||||||
|
- Fixed a crash in nDPIsrvd if a collector closes a connection
|
||||||
|
- Support `nDPId` to send it's data to a UDP endpoint instead of a nDPIsrvd collector
|
||||||
|
- Added events and flow states documentation
|
||||||
|
- Added basic systemd support
|
||||||
|
- Fixed a bug in base64 encoding which could lead to invalid base64 strings
|
||||||
|
- Added some machine learning examples
|
||||||
|
- Fixed various smaller bugs
|
||||||
|
- Fixed nDPIsrvd bug which causes invalid JSON messages sent to Distributors
|
||||||
|
|
||||||
|
#### nDPId 1.5 (Apr 2022)
|
||||||
|
|
||||||
|
- Improved nDPId cross compilation
|
||||||
|
- zLib flow memory compression (Experimental!)
|
||||||
|
- Memory profiling for nDPId-test
|
||||||
|
- JSMN with parent link support for subtoken iteration
|
||||||
|
- Refactored nDPIsrvd buffer and buffer bloat handling
|
||||||
|
- Upgraded JSMN/uthash
|
||||||
|
- Improved nDPIsrvd.(h|py) debugging capability for client apps
|
||||||
|
- Advanced flow usage logging usable for memory profiling
|
||||||
|
- Support for dissection additional layer2/layer3 protocols
|
||||||
|
- Serialize more JSON information
|
||||||
|
- Add TCP/IP support for nDPIsrvd
|
||||||
|
- Improved nDPIsrvd connection lost behaviour
|
||||||
|
- Reworked Python/C distributor API
|
||||||
|
- Support read()/recv() timeouts and nonblocking I/O
|
||||||
|
|
||||||
|
|
||||||
|
#### nDPId 1.4 (Jun 2021)
|
||||||
|
|
||||||
|
- Use layer4 specific flow timeouts for nDPId
|
||||||
|
- Reworked layer4 flow length names and calculations (use only layer4 payload w/o any previous headers) for nDPId
|
||||||
|
- Build system cleanup and cosmetics
|
||||||
|
|
||||||
|
|
||||||
|
#### nDPId 1.3 (May 2021)
|
||||||
|
|
||||||
|
- Added missing datalink layer types
|
||||||
|
|
||||||
|
|
||||||
|
#### nDPId 1.2 (May 2021)
|
||||||
|
|
||||||
|
- OpenWrt compatible build system
|
||||||
|
|
||||||
|
|
||||||
|
#### nDPId 1.1 (May 2021)
|
||||||
|
|
||||||
|
- Added License information
|
||||||
|
|
||||||
|
|
||||||
|
#### nDPId 1.0 (May 2021)
|
||||||
|
|
||||||
|
- First public release
|
||||||
706
CMakeLists.txt
706
CMakeLists.txt
@@ -1,35 +1,240 @@
|
|||||||
cmake_minimum_required(VERSION 3.12.4)
|
cmake_minimum_required(VERSION 3.12.4)
|
||||||
project(nDPId C)
|
project(nDPId C)
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
||||||
|
if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
|
||||||
|
message(STATUS "${CMAKE_C_COMPILER} supports C11 standard.")
|
||||||
|
else ()
|
||||||
|
message(FATAL_ERROR "C Compiler with C11 standard needed. Therefore a gcc compiler with a version equal or higher than 4.7 is needed.")
|
||||||
|
endif()
|
||||||
|
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_DEFAULT_SOURCE=1 -D_GNU_SOURCE=1")
|
||||||
|
if("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
|
||||||
|
message(FATAL_ERROR "In-source builds are not allowed.\n"
|
||||||
|
"Please remove ${PROJECT_SOURCE_DIR}/CMakeCache.txt\n"
|
||||||
|
"and\n"
|
||||||
|
"${PROJECT_SOURCE_DIR}/CMakeFiles\n"
|
||||||
|
"Create a build directory somewhere and run CMake again.\n"
|
||||||
|
"Or run: 'cmake -S ${PROJECT_SOURCE_DIR} -B ./your-custom-build-dir [CMAKE-OPTIONS]'")
|
||||||
|
endif()
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
function(initialize_submodule DIRECTORY)
|
set(CPACK_PACKAGE_CONTACT "toni@impl.cc")
|
||||||
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${DIRECTORY}/.git)
|
set(CPACK_DEBIAN_PACKAGE_NAME "nDPId")
|
||||||
find_package(Git QUIET REQUIRED)
|
set(CPACK_DEBIAN_PACKAGE_SECTION "network")
|
||||||
message(STATUS "${CMAKE_CURRENT_SOURCE_DIR}/${DIRECTORY}/.git does not exist. "
|
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "nDPId is a set of daemons and tools to capture, process and classify network traffic.")
|
||||||
"Initializing ${DIRECTORY} submodule ...")
|
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Toni Uhlig <toni@impl.cc>")
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init ${DIRECTORY}
|
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_SOURCE_DIR}/packages/debian/preinst;${CMAKE_SOURCE_DIR}/packages/debian/prerm;${CMAKE_SOURCE_DIR}/packages/debian/postrm")
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
|
||||||
RESULT_VARIABLE GIT_EXIT_CODE)
|
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||||
if(NOT GIT_EXIT_CODE EQUAL "0")
|
set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON)
|
||||||
message(FATAL_ERROR "${GIT_EXECUTABLE} submodule update --init dependencies/${DIRECTORY} "
|
set(CPACK_RPM_PACKAGE_LICENSE "GPL-3")
|
||||||
"failed with exit code ${GIT_EXIT_CODE}, please checkout submodules")
|
set(CPACK_RPM_PACKAGE_VENDOR "Toni Uhlig")
|
||||||
|
set(CPACK_RPM_PACKAGE_URL "https://www.github.com/utoni/nDPId.git")
|
||||||
|
set(CPACK_RPM_PACKAGE_DESCRIPTION "nDPId is a set of daemons and tools to capture, process and classify network traffic.")
|
||||||
|
set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${CMAKE_SOURCE_DIR}/packages/redhat/pre_install")
|
||||||
|
set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE "${CMAKE_SOURCE_DIR}/packages/redhat/pre_uninstall")
|
||||||
|
set(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE "${CMAKE_SOURCE_DIR}/packages/redhat/post_uninstall")
|
||||||
|
set(CPACK_STRIP_FILES ON)
|
||||||
|
set(CPACK_PACKAGE_VERSION_MAJOR 1)
|
||||||
|
set(CPACK_PACKAGE_VERSION_MINOR 7)
|
||||||
|
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||||
|
# Note: CPACK_PACKAGING_INSTALL_PREFIX and CMAKE_INSTALL_PREFIX are *not* the same.
|
||||||
|
# It is used only to ease environment file loading via systemd.
|
||||||
|
set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
set(CMAKE_MACOSX_RPATH 1)
|
||||||
|
|
||||||
|
include(CPack)
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
include(CheckLibraryExists)
|
||||||
|
include(CheckEpoll)
|
||||||
|
|
||||||
|
check_epoll(HAS_EPOLL)
|
||||||
|
if(HAS_EPOLL)
|
||||||
|
option(FORCE_POLL "Force the use of poll() instead of epoll()." OFF)
|
||||||
|
if(NOT FORCE_POLL)
|
||||||
|
set(EPOLL_DEFS "-DENABLE_EPOLL=1")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(BUILD_EXAMPLES)
|
||||||
|
message(FATAL_ERROR "Examples are using epoll event I/O. Without epoll available, you can not build/run those.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT MATH_FUNCTION_EXISTS AND NOT NEED_LINKING_AGAINST_LIBM)
|
||||||
|
CHECK_FUNCTION_EXISTS(log2f MATH_FUNCTION_EXISTS)
|
||||||
|
if(NOT MATH_FUNCTION_EXISTS)
|
||||||
|
unset(MATH_FUNCTION_EXISTS CACHE)
|
||||||
|
list(APPEND CMAKE_REQUIRED_LIBRARIES m)
|
||||||
|
CHECK_FUNCTION_EXISTS(log2f MATH_FUNCTION_EXISTS)
|
||||||
|
if(MATH_FUNCTION_EXISTS)
|
||||||
|
set(NEED_LINKING_AGAINST_LIBM TRUE CACHE BOOL "" FORCE)
|
||||||
|
else()
|
||||||
|
check_library_exists(m sqrt "" NEED_LINKING_AGAINST_LIBM)
|
||||||
|
if(NOT NEED_LINKING_AGAINST_LIBM)
|
||||||
|
# Was not able to figure out if explicit linkage against libm is required.
|
||||||
|
# Forcing libm linkage. Good idea?
|
||||||
|
set(NEED_LINKING_AGAINST_LIBM TRUE CACHE BOOL "" FORCE)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endfunction(initialize_submodule)
|
endif()
|
||||||
|
|
||||||
|
if(NEED_LINKING_AGAINST_LIBM)
|
||||||
|
set(LIBM_LIB "-lm")
|
||||||
|
else()
|
||||||
|
set(LIBM_LIB "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(ENABLE_COVERAGE "Generate a code coverage report using lcov/genhtml." OFF)
|
||||||
option(ENABLE_SANITIZER "Enable ASAN/LSAN/UBSAN." OFF)
|
option(ENABLE_SANITIZER "Enable ASAN/LSAN/UBSAN." OFF)
|
||||||
option(ENABLE_SANITIZER_THREAD "Enable TSAN (does not work together with ASAN)." OFF)
|
option(ENABLE_SANITIZER_THREAD "Enable TSAN (does not work together with ASAN)." OFF)
|
||||||
option(ENABLE_MEMORY_PROFILING "Enable dynamic memory tracking." OFF)
|
option(ENABLE_MEMORY_PROFILING "Enable dynamic memory tracking." OFF)
|
||||||
|
option(ENABLE_ZLIB "Enable zlib support for nDPId (experimental)." OFF)
|
||||||
|
option(ENABLE_SYSTEMD "Install systemd components." OFF)
|
||||||
|
option(ENABLE_CRYPTO "Enable OpenSSL cryptographic support in nDPId/nDPIsrvd." OFF)
|
||||||
option(BUILD_EXAMPLES "Build C examples." ON)
|
option(BUILD_EXAMPLES "Build C examples." ON)
|
||||||
|
option(BUILD_RUST_EXAMPLES "Build Rust examples." OFF)
|
||||||
|
if(BUILD_EXAMPLES)
|
||||||
|
option(ENABLE_DBUS "Build DBus notification example." OFF)
|
||||||
|
option(ENABLE_CURL "Build influxdb data write example." OFF)
|
||||||
|
endif()
|
||||||
|
option(ENABLE_PFRING "Enable PF_RING support for nDPId (experimental)" OFF)
|
||||||
option(BUILD_NDPI "Clone and build nDPI from github." OFF)
|
option(BUILD_NDPI "Clone and build nDPI from github." OFF)
|
||||||
option(NDPI_NO_PKGCONFIG "Do not use pkgconfig to search for libnDPI." OFF)
|
|
||||||
|
|
||||||
set(STATIC_LIBNDPI_INSTALLDIR "" CACHE STRING "Path to a installation directory of libnDPI e.g. /opt/libnDPI/usr")
|
if(ENABLE_PFRING)
|
||||||
|
option(PFRING_LINK_STATIC "Link against a static version of pfring." ON)
|
||||||
|
set(PFRING_KERNEL_INC "" CACHE STRING "Path to PFRING kernel module include directory.")
|
||||||
|
set(PFRING_DEFS "-DENABLE_PFRING=1")
|
||||||
|
|
||||||
add_executable(nDPId nDPId.c utils.c)
|
if(PFRING_KERNEL_INC STREQUAL "")
|
||||||
add_executable(nDPIsrvd nDPIsrvd.c utils.c)
|
message(FATAL_ERROR "PFRING_KERNEL_INC needs to be set to the PFRING kernel module include directory.")
|
||||||
add_executable(nDPId-test nDPId-test.c utils.c)
|
endif()
|
||||||
|
if(NOT EXISTS "${PFRING_KERNEL_INC}/linux/pf_ring.h")
|
||||||
|
message(FATAL_ERROR "Expected to find <linux/pf_ring.h> below ${PFRING_KERNEL_INC}, but none found.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(PFRING_INSTALLDIR "/opt/PF_RING/usr" CACHE STRING "")
|
||||||
|
set(PFRING_INC "${PFRING_INSTALLDIR}/include")
|
||||||
|
|
||||||
|
if(NOT EXISTS "${PFRING_INC}")
|
||||||
|
message(FATAL_ERROR "Include directory \"${PFRING_INC}\" does not exist!")
|
||||||
|
endif()
|
||||||
|
if(PFRING_LINK_STATIC)
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
if(EXISTS "${PFRING_INSTALLDIR}/lib64")
|
||||||
|
set(STATIC_PFRING_LIB "${PFRING_INSTALLDIR}/lib64/libpfring.a")
|
||||||
|
else()
|
||||||
|
set(STATIC_PFRING_LIB "${PFRING_INSTALLDIR}/lib/libpfring.a")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(EXISTS "${PFRING_INSTALLDIR}/lib32")
|
||||||
|
set(STATIC_PFRING_LIB "${PFRING_INSTALLDIR}/lib32/libpfring.a")
|
||||||
|
else()
|
||||||
|
set(STATIC_PFRING_LIB "${PFRING_INSTALLDIR}/lib/libpfring.a")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${STATIC_PFRING_LIB}")
|
||||||
|
message(FATAL_ERROR "Static library \"${STATIC_PFRING_LIB}\" does not exist!")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
if(EXISTS "${PFRING_INSTALLDIR}/lib64")
|
||||||
|
find_library(PF_RING_LIB pfring PATHS "${PFRING_INSTALLDIR}/lib64")
|
||||||
|
else()
|
||||||
|
find_library(PF_RING_LIB pfring PATHS "${PFRING_INSTALLDIR}/lib")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(EXISTS "${PFRING_INSTALLDIR}/lib32")
|
||||||
|
find_library(PF_RING_LIB pfring PATHS "${PFRING_INSTALLDIR}/lib32")
|
||||||
|
else()
|
||||||
|
find_library(PF_RING_LIB pfring PATHS "${PFRING_INSTALLDIR}/lib")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT PF_RING_LIB)
|
||||||
|
message(FATAL_ERROR "libpfring.so not found below ${PFRING_INSTALLDIR}/{lib,lib32,lib64}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${PFRING_INSTALLDIR}/include/pfring.h")
|
||||||
|
message(FATAL_ERROR "Expected to find <include/pfring.h> inside ${PFRING_INSTALLDIR}, but none found.")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
unset(PFRING_INSTALLDIR CACHE)
|
||||||
|
unset(PFRING_INC CACHE)
|
||||||
|
unset(STATIC_PFRING_LIB CACHE)
|
||||||
|
unset(PFRING_LINK_STATIC CACHE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_NDPI)
|
||||||
|
option(BUILD_NDPI_FORCE_GIT_UPDATE "Forcefully instruments nDPI build script to update the git submodule." OFF)
|
||||||
|
unset(NDPI_NO_PKGCONFIG CACHE)
|
||||||
|
unset(STATIC_LIBNDPI_INSTALLDIR CACHE)
|
||||||
|
else()
|
||||||
|
option(NDPI_NO_PKGCONFIG "Do not use pkgconfig to search for libnDPI." OFF)
|
||||||
|
if(NDPI_NO_PKGCONFIG)
|
||||||
|
set(STATIC_LIBNDPI_INSTALLDIR "/opt/libnDPI/usr" CACHE STRING "Path to a installation directory of libnDPI e.g. /opt/libnDPI/usr")
|
||||||
|
if(STATIC_LIBNDPI_INSTALLDIR STREQUAL "")
|
||||||
|
message(FATAL_ERROR "STATIC_LIBNDPI_INSTALLDIR can not be an empty string within your configuration!")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
unset(STATIC_LIBNDPI_INSTALLDIR CACHE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(STATIC_LIBNDPI_INSTALLDIR OR BUILD_NDPI OR NDPI_NO_PKGCONFIG)
|
||||||
|
option(NDPI_WITH_GCRYPT "Link static libndpi library against libgcrypt." OFF)
|
||||||
|
option(NDPI_WITH_PCRE "Link static libndpi library against libpcre." OFF)
|
||||||
|
option(NDPI_WITH_MAXMINDDB "Link static libndpi library against libmaxminddb." OFF)
|
||||||
|
else()
|
||||||
|
unset(NDPI_WITH_GCRYPT CACHE)
|
||||||
|
unset(NDPI_WITH_PCRE CACHE)
|
||||||
|
unset(NDPI_WITH_MAXMINDDB CACHE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_PFRING)
|
||||||
|
set(NDPID_PFRING_SRCS npfring.c)
|
||||||
|
endif()
|
||||||
|
if(ENABLE_CRYPTO)
|
||||||
|
set(CRYPTO_SRCS ncrypt.c)
|
||||||
|
endif()
|
||||||
|
add_executable(nDPId nDPId.c ${NDPID_PFRING_SRCS} ${CRYPTO_SRCS} nio.c utils.c)
|
||||||
|
add_executable(nDPIsrvd nDPIsrvd.c nio.c utils.c)
|
||||||
|
add_executable(nDPId-test nDPId-test.c ${NDPID_PFRING_SRCS} ${CRYPTO_SRCS})
|
||||||
|
|
||||||
|
add_custom_target(umask_check)
|
||||||
|
add_custom_command(
|
||||||
|
TARGET umask_check
|
||||||
|
PRE_BUILD
|
||||||
|
COMMAND ${CMAKE_SOURCE_DIR}/scripts/umask-check.sh
|
||||||
|
)
|
||||||
|
add_dependencies(nDPId umask_check)
|
||||||
|
|
||||||
|
add_custom_target(dist)
|
||||||
|
add_custom_command(
|
||||||
|
TARGET dist
|
||||||
|
PRE_BUILD
|
||||||
|
COMMAND "${CMAKE_SOURCE_DIR}/scripts/make-dist.sh"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(daemon)
|
||||||
|
add_custom_command(
|
||||||
|
TARGET daemon
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND env nDPIsrvd_ARGS='-C 1024' "${CMAKE_SOURCE_DIR}/scripts/daemon.sh" "$<TARGET_FILE:nDPId>" "$<TARGET_FILE:nDPIsrvd>"
|
||||||
|
)
|
||||||
|
add_dependencies(daemon nDPId nDPIsrvd)
|
||||||
|
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(BUILD_NDPI)
|
if(BUILD_NDPI)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
@@ -37,64 +242,169 @@ if(BUILD_NDPI)
|
|||||||
COMMAND "${CMAKE_SOURCE_DIR}/test/run_tests.sh"
|
COMMAND "${CMAKE_SOURCE_DIR}/test/run_tests.sh"
|
||||||
"${CMAKE_SOURCE_DIR}/libnDPI"
|
"${CMAKE_SOURCE_DIR}/libnDPI"
|
||||||
"$<TARGET_FILE:nDPId-test>")
|
"$<TARGET_FILE:nDPId-test>")
|
||||||
|
if(NDPI_WITH_PCRE OR NDPI_WITH_MAXMINDDB)
|
||||||
|
message(WARNING "NDPI_WITH_PCRE or NDPI_WITH_MAXMINDDB enabled.\n"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/test/run_tests.sh or ctest will fail!")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -DJSMN_STATIC=1 -DJSMN_STRICT=1")
|
if(ENABLE_COVERAGE)
|
||||||
set(BUILD_NDPI_CONFIGURE_OPTS "")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
|
||||||
|
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --coverage")
|
||||||
|
add_custom_target(coverage DEPENDS "${CMAKE_BINARY_DIR}/coverage_report/nDPId/index.html")
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT "${CMAKE_BINARY_DIR}/coverage_report/nDPId/index.html"
|
||||||
|
COMMAND lcov --directory "${CMAKE_BINARY_DIR}" --directory "${CMAKE_SOURCE_DIR}/libnDPI" --capture --output-file "${CMAKE_BINARY_DIR}/lcov.info"
|
||||||
|
COMMAND genhtml -o "${CMAKE_BINARY_DIR}/coverage_report" "${CMAKE_BINARY_DIR}/lcov.info"
|
||||||
|
DEPENDS nDPId nDPId-test nDPIsrvd
|
||||||
|
)
|
||||||
|
add_custom_target(coverage-clean)
|
||||||
|
add_custom_command(
|
||||||
|
TARGET coverage-clean
|
||||||
|
COMMAND find "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/libnDPI" -name "*.gcda" -delete
|
||||||
|
POST_BUILD
|
||||||
|
)
|
||||||
|
add_custom_target(coverage-view)
|
||||||
|
add_custom_command(
|
||||||
|
TARGET coverage-view
|
||||||
|
COMMAND cd "${CMAKE_BINARY_DIR}/coverage_report" && python3 -m http.server
|
||||||
|
POST_BUILD
|
||||||
|
)
|
||||||
|
add_dependencies(coverage-view coverage)
|
||||||
|
endif()
|
||||||
|
if(ENABLE_SANITIZER)
|
||||||
|
# TODO: Check for `-fsanitize-memory-track-origins` and add if available?
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined -fno-sanitize=alignment -fsanitize=enum -fsanitize=leak")
|
||||||
|
endif()
|
||||||
|
if(ENABLE_SANITIZER_THREAD)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize=alignment -fsanitize=enum -fsanitize=thread")
|
||||||
|
endif()
|
||||||
|
if(ENABLE_ZLIB)
|
||||||
|
set(ZLIB_DEFS "-DENABLE_ZLIB=1")
|
||||||
|
pkg_check_modules(ZLIB REQUIRED zlib)
|
||||||
|
endif()
|
||||||
|
if(BUILD_EXAMPLES)
|
||||||
|
if(ENABLE_DBUS)
|
||||||
|
pkg_check_modules(DBUS REQUIRED dbus-1)
|
||||||
|
endif()
|
||||||
|
if(ENABLE_CURL)
|
||||||
|
pkg_check_modules(CURL REQUIRED libcurl)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(BUILD_NDPI)
|
||||||
|
if(NDPI_WITH_GCRYPT)
|
||||||
|
message(STATUS "nDPI: Enable GCRYPT")
|
||||||
|
set(NDPI_ADDITIONAL_ARGS "${NDPI_ADDITIONAL_ARGS} --with-local-libgcrypt")
|
||||||
|
endif()
|
||||||
|
if(NDPI_WITH_PCRE)
|
||||||
|
message(STATUS "nDPI: Enable PCRE")
|
||||||
|
set(NDPI_ADDITIONAL_ARGS "${NDPI_ADDITIONAL_ARGS} --with-pcre2")
|
||||||
|
endif()
|
||||||
|
if(NDPI_WITH_MAXMINDDB)
|
||||||
|
message(STATUS "nDPI: Enable MAXMINDDB")
|
||||||
|
set(NDPI_ADDITIONAL_ARGS "${NDPI_ADDITIONAL_ARGS} --with-maxminddb")
|
||||||
|
endif()
|
||||||
|
if(ENABLE_COVERAGE)
|
||||||
|
message(STATUS "nDPI: Enable Coverage")
|
||||||
|
set(NDPI_ADDITIONAL_ARGS "${NDPI_ADDITIONAL_ARGS} --enable-code-coverage")
|
||||||
|
endif()
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "")
|
||||||
|
message(STATUS "nDPI: Enable Debug Build")
|
||||||
|
set(NDPI_ADDITIONAL_ARGS "${NDPI_ADDITIONAL_ARGS} --enable-debug-build --enable-debug-messages")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND git describe --tags
|
||||||
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
|
OUTPUT_VARIABLE GIT_VERSION ERROR_QUIET)
|
||||||
|
string(STRIP "${GIT_VERSION}" GIT_VERSION)
|
||||||
|
if(GIT_VERSION STREQUAL "" OR NOT IS_DIRECTORY "${CMAKE_SOURCE_DIR}/.git")
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "")
|
||||||
|
set(GIT_VERSION "${CPACK_PACKAGE_VERSION}-pre")
|
||||||
|
else()
|
||||||
|
set(GIT_VERSION "${CPACK_PACKAGE_VERSION}-release")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
set(PKG_VERSION "${CPACK_PACKAGE_VERSION}")
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
|
||||||
|
set(NDPID_DEFS -DJSMN_STATIC=1 -DJSMN_STRICT=1 -DJSMN_PARENT_LINKS=1)
|
||||||
|
set(NDPID_DEPS_INC "${CMAKE_SOURCE_DIR}"
|
||||||
|
"${CMAKE_SOURCE_DIR}/dependencies"
|
||||||
|
"${CMAKE_SOURCE_DIR}/dependencies/jsmn"
|
||||||
|
"${CMAKE_SOURCE_DIR}/dependencies/uthash/src")
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
add_definitions("-DCROSS_COMPILATION=1")
|
||||||
|
endif()
|
||||||
if(ENABLE_MEMORY_PROFILING)
|
if(ENABLE_MEMORY_PROFILING)
|
||||||
set(MEMORY_PROFILING_CFLAGS "-DENABLE_MEMORY_PROFILING=1"
|
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT CMAKE_BUILD_TYPE STREQUAL "")
|
||||||
"-Duthash_malloc=nDPIsrvd_uthash_malloc"
|
message(WARNING "ENABLE_MEMORY_PROFILING should not be used in production environments.")
|
||||||
"-Duthash_free=nDPIsrvd_uthash_free")
|
endif()
|
||||||
|
add_definitions("-DENABLE_MEMORY_PROFILING=1"
|
||||||
|
"-Duthash_malloc=nDPIsrvd_uthash_malloc"
|
||||||
|
"-Duthash_free=nDPIsrvd_uthash_free")
|
||||||
else()
|
else()
|
||||||
set(MEMORY_PROFILING_CFLAGS "")
|
set(NDPID_TEST_MPROF_DEFS "-DENABLE_MEMORY_PROFILING=1")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g3 -fno-omit-frame-pointer -fno-inline")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g3 -fno-omit-frame-pointer -fno-inline")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_SANITIZER AND ENABLE_SANITIZER_THREAD)
|
if(ENABLE_SANITIZER AND ENABLE_SANITIZER_THREAD)
|
||||||
message(STATUS_FATAL "ENABLE_SANITIZER and ENABLE_SANITIZER_THREAD can not be used together!")
|
message(FATAL_ERROR "ENABLE_SANITIZER and ENABLE_SANITIZER_THREAD can not be used together!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_SANITIZER)
|
if(BUILD_NDPI)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined -fsanitize=enum -fsanitize=leak")
|
|
||||||
set(BUILD_NDPI_CONFIGURE_OPTS "${BUILD_NDPI_CONFIGURE_OPTS} --with-sanitizer")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ENABLE_SANITIZER_THREAD)
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fsanitize=enum -fsanitize=thread")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(STATIC_LIBNDPI_INSTALLDIR STREQUAL "" AND BUILD_NDPI)
|
|
||||||
initialize_submodule(libnDPI)
|
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
libnDPI
|
libnDPI
|
||||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libnDPI
|
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libnDPI
|
||||||
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/libnDPI/autogen.sh
|
DOWNLOAD_COMMAND ""
|
||||||
--prefix=${CMAKE_CURRENT_BINARY_DIR}/libnDPI
|
CONFIGURE_COMMAND env
|
||||||
${BUILD_NDPI_CONFIGURE_OPTS}
|
CC=${CMAKE_C_COMPILER}
|
||||||
BUILD_COMMAND make
|
CXX=false
|
||||||
|
AR=${CMAKE_AR}
|
||||||
|
RANLIB=${CMAKE_RANLIB}
|
||||||
|
PKG_CONFIG=${PKG_CONFIG_EXECUTABLE}
|
||||||
|
CFLAGS=${CMAKE_C_FLAGS}
|
||||||
|
LDFLAGS=${CMAKE_MODULE_LINKER_FLAGS}
|
||||||
|
ADDITIONAL_ARGS=${NDPI_ADDITIONAL_ARGS}
|
||||||
|
MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
|
||||||
|
DEST_INSTALL=${CMAKE_BINARY_DIR}/libnDPI
|
||||||
|
FORCE_GIT_UPDATE=${BUILD_NDPI_FORCE_GIT_UPDATE}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/scripts/get-and-build-libndpi.sh
|
||||||
|
BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/libnDPI/lib/libndpi.a
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
BUILD_IN_SOURCE 1)
|
BUILD_IN_SOURCE 1)
|
||||||
|
|
||||||
|
add_custom_target(clean-libnDPI
|
||||||
|
COMMAND ${CMAKE_BUILD_TOOL} clean
|
||||||
|
COMMAND rm -rf ${CMAKE_BINARY_DIR}/libnDPI
|
||||||
|
COMMAND rm -f ${CMAKE_BINARY_DIR}/libnDPI-prefix/src/libnDPI-stamp/libnDPI-configure
|
||||||
|
)
|
||||||
|
|
||||||
set(STATIC_LIBNDPI_INSTALLDIR "${CMAKE_BINARY_DIR}/libnDPI")
|
set(STATIC_LIBNDPI_INSTALLDIR "${CMAKE_BINARY_DIR}/libnDPI")
|
||||||
add_dependencies(nDPId libnDPI)
|
add_dependencies(nDPId libnDPI)
|
||||||
add_dependencies(nDPId-test libnDPI)
|
add_dependencies(nDPId-test libnDPI)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT STATIC_LIBNDPI_INSTALLDIR STREQUAL "" OR BUILD_NDPI OR NDPI_NO_PKGCONFIG)
|
if(ENABLE_CRYPTO)
|
||||||
option(NDPI_WITH_GCRYPT "Link static libndpi library against libgcrypt." ON)
|
find_package(OpenSSL REQUIRED)
|
||||||
option(NDPI_WITH_PCRE "Link static libndpi library against libpcre." OFF)
|
set(OSSL_DEFS "-DENABLE_CRYPTO=1")
|
||||||
option(NDPI_WITH_MAXMINDDB "Link static libndpi library against libmaxminddb." OFF)
|
set(OSSL_LIBRARY "${OPENSSL_SSL_LIBRARY}" "${OPENSSL_CRYPTO_LIBRARY}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(STATIC_LIBNDPI_INSTALLDIR OR BUILD_NDPI OR NDPI_NO_PKGCONFIG)
|
||||||
if(NDPI_WITH_GCRYPT)
|
if(NDPI_WITH_GCRYPT)
|
||||||
find_package(GCRYPT "1.4.2" REQUIRED)
|
find_package(GCRYPT "1.4.2" REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NDPI_WITH_PCRE)
|
if(NDPI_WITH_PCRE)
|
||||||
pkg_check_modules(PCRE REQUIRED libpcre>=8.39)
|
pkg_check_modules(PCRE REQUIRED libpcre2-8)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NDPI_WITH_MAXMINDDB)
|
if(NDPI_WITH_MAXMINDDB)
|
||||||
@@ -102,107 +412,275 @@ if(NOT STATIC_LIBNDPI_INSTALLDIR STREQUAL "" OR BUILD_NDPI OR NDPI_NO_PKGCONFIG)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT STATIC_LIBNDPI_INSTALLDIR STREQUAL "" OR BUILD_NDPI)
|
if(STATIC_LIBNDPI_INSTALLDIR OR BUILD_NDPI)
|
||||||
|
add_definitions("-DLIBNDPI_STATIC=1")
|
||||||
set(STATIC_LIBNDPI_INC "${STATIC_LIBNDPI_INSTALLDIR}/include/ndpi")
|
set(STATIC_LIBNDPI_INC "${STATIC_LIBNDPI_INSTALLDIR}/include/ndpi")
|
||||||
set(STATIC_LIBNDPI_LIB "${STATIC_LIBNDPI_INSTALLDIR}/lib/libndpi.a")
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
if(EXISTS "${STATIC_LIBNDPI_INSTALLDIR}/lib64/libndpi.a")
|
||||||
|
set(STATIC_LIBNDPI_LIB "${STATIC_LIBNDPI_INSTALLDIR}/lib64/libndpi.a")
|
||||||
|
else()
|
||||||
|
set(STATIC_LIBNDPI_LIB "${STATIC_LIBNDPI_INSTALLDIR}/lib/libndpi.a")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(EXISTS "${STATIC_LIBNDPI_INSTALLDIR}/lib32/libndpi.a")
|
||||||
|
set(STATIC_LIBNDPI_LIB "${STATIC_LIBNDPI_INSTALLDIR}/lib32/libndpi.a")
|
||||||
|
else()
|
||||||
|
set(STATIC_LIBNDPI_LIB "${STATIC_LIBNDPI_INSTALLDIR}/lib/libndpi.a")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(STATIC_LIBNDPI_INSTALLDIR AND NOT BUILD_NDPI)
|
||||||
|
if(NOT EXISTS "${STATIC_LIBNDPI_INC}" OR NOT EXISTS "${STATIC_LIBNDPI_LIB}")
|
||||||
|
message(FATAL_ERROR "Include directory \"${STATIC_LIBNDPI_INC}\" or\n"
|
||||||
|
"static library \"${STATIC_LIBNDPI_LIB}\" does not exist!")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
unset(DEFAULT_NDPI_INCLUDE CACHE)
|
||||||
|
unset(pkgcfg_lib_NDPI_ndpi CACHE)
|
||||||
else()
|
else()
|
||||||
if(NOT NDPI_NO_PKGCONFIG)
|
if(NOT NDPI_NO_PKGCONFIG)
|
||||||
pkg_check_modules(NDPI REQUIRED libndpi>=3.5.0)
|
pkg_check_modules(NDPI REQUIRED libndpi>=5.0.0)
|
||||||
|
if(NOT pkgcfg_lib_NDPI_ndpi)
|
||||||
|
find_package(NDPI "5.0.0" REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(STATIC_LIBNDPI_INC "")
|
unset(STATIC_LIBNDPI_INC CACHE)
|
||||||
set(STATIC_LIBNDPI_LIB "")
|
unset(STATIC_LIBNDPI_LIB CACHE)
|
||||||
else()
|
|
||||||
set(LIBNDPI_INC "" CACHE STRING "/usr/include/ndpi")
|
|
||||||
set(LIBNDPI_LIB "" CACHE STRING "/usr/lib/libndpi.a")
|
|
||||||
|
|
||||||
set(STATIC_LIBNDPI_INC "${LIBNDPI_INC}")
|
|
||||||
set(STATIC_LIBNDPI_LIB "${LIBNDPI_LIB}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(DEFAULT_NDPI_INCLUDE ${NDPI_INCLUDE_DIRS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(PCAP "1.8.1" REQUIRED)
|
pkg_check_modules(PCAP libpcap>=1.9.0) # no *.pc file before 1.9.0
|
||||||
target_compile_options(nDPId PRIVATE ${MEMORY_PROFILING_CFLAGS} "-pthread")
|
if(NOT pkgcfg_lib_PCAP_pcap)
|
||||||
target_include_directories(nDPId PRIVATE "${STATIC_LIBNDPI_INC}" "${NDPI_INCLUDEDIR}" "${NDPI_INCLUDEDIR}/ndpi")
|
pkg_check_modules(PCAP libpcap>=1.8.1) # seems like some distributions provide their own *.pc file for 1.8.1 (e.g. Ubuntu-18.04)
|
||||||
target_link_libraries(nDPId "${STATIC_LIBNDPI_LIB}" "${pkgcfg_lib_NDPI_ndpi}"
|
endif()
|
||||||
"${pkgcfg_lib_PCRE_pcre}" "${pkgcfg_lib_MAXMINDDB_maxminddb}"
|
if(NOT pkgcfg_lib_PCAP_pcap)
|
||||||
"${GCRYPT_LIBRARY}" "${PCAP_LIBRARY}"
|
find_package(PCAP "1.9.0" REQUIRED)
|
||||||
"-pthread")
|
endif()
|
||||||
|
|
||||||
target_compile_options(nDPId PRIVATE ${MEMORY_PROFILING_CFLAGS})
|
target_compile_options(nDPId PRIVATE "-pthread")
|
||||||
target_include_directories(nDPIsrvd PRIVATE
|
target_compile_definitions(nDPId PRIVATE -D_GNU_SOURCE=1 -DPKG_VERSION=\"${PKG_VERSION}\" -DGIT_VERSION=\"${GIT_VERSION}\"
|
||||||
"${CMAKE_SOURCE_DIR}"
|
${NDPID_DEFS} ${EPOLL_DEFS} ${ZLIB_DEFS} ${PFRING_DEFS} ${OSSL_DEFS})
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies"
|
target_include_directories(nDPId PRIVATE "${STATIC_LIBNDPI_INC}" "${DEFAULT_NDPI_INCLUDE}" ${NDPID_DEPS_INC} ${PFRING_KERNEL_INC} ${PFRING_INC})
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies/jsmn"
|
target_link_libraries(nDPId "${STATIC_LIBNDPI_LIB}" "${STATIC_PFRING_LIB}" "${pkgcfg_lib_PCAP_pcap}" "${pkgcfg_lib_NDPI_ndpi}"
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies/uthash/src")
|
"${pkgcfg_lib_PCRE_pcre2-8}" "${pkgcfg_lib_MAXMINDDB_maxminddb}" "${pkgcfg_lib_ZLIB_z}"
|
||||||
|
"${GCRYPT_LIBRARY}" "${GCRYPT_ERROR_LIBRARY}" "${PCAP_LIBRARY}" "${LIBM_LIB}" "${PF_RING_LIB}"
|
||||||
|
"${OSSL_LIBRARY}" "-pthread")
|
||||||
|
|
||||||
|
target_compile_definitions(nDPIsrvd PRIVATE -D_GNU_SOURCE=1 -DPKG_VERSION=\"${PKG_VERSION}\" -DGIT_VERSION=\"${GIT_VERSION}\" ${NDPID_DEFS} ${EPOLL_DEFS})
|
||||||
|
target_include_directories(nDPIsrvd PRIVATE ${NDPID_DEPS_INC})
|
||||||
|
|
||||||
|
target_compile_options(nDPId-test PRIVATE "-Wno-unused-function" "-pthread")
|
||||||
|
target_compile_definitions(nDPId-test PRIVATE -D_GNU_SOURCE=1 -DNO_MAIN=1 -DPKG_VERSION=\"${PKG_VERSION}\" -DGIT_VERSION=\"${GIT_VERSION}\"
|
||||||
|
${NDPID_DEFS} ${EPOLL_DEFS} ${ZLIB_DEFS} ${PFRING_DEFS} ${OSSL_DEFS} ${NDPID_TEST_MPROF_DEFS})
|
||||||
target_include_directories(nDPId-test PRIVATE
|
target_include_directories(nDPId-test PRIVATE
|
||||||
"${CMAKE_SOURCE_DIR}"
|
"${STATIC_LIBNDPI_INC}" "${DEFAULT_NDPI_INCLUDE}" ${NDPID_DEPS_INC} ${PFRING_KERNEL_INC} ${PFRING_INC})
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies"
|
target_link_libraries(nDPId-test "${STATIC_LIBNDPI_LIB}" "${STATIC_PFRING_LIB}" "${pkgcfg_lib_PCAP_pcap}" "${pkgcfg_lib_NDPI_ndpi}"
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies/jsmn"
|
"${pkgcfg_lib_PCRE_pcre2-8}" "${pkgcfg_lib_MAXMINDDB_maxminddb}" "${pkgcfg_lib_ZLIB_z}"
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies/uthash/src")
|
"${GCRYPT_LIBRARY}" "${GCRYPT_ERROR_LIBRARY}" "${PCAP_LIBRARY}" "${LIBM_LIB}" "${PF_RING_LIB}"
|
||||||
target_compile_options(nDPId-test PRIVATE ${MEMORY_PROFILING_CFLAGS} "-Wno-unused-function" "-pthread")
|
"${OSSL_LIBRARY}" "-pthread")
|
||||||
target_include_directories(nDPId-test PRIVATE "${STATIC_LIBNDPI_INC}" "${NDPI_INCLUDEDIR}" "${NDPI_INCLUDEDIR}/ndpi")
|
|
||||||
target_compile_definitions(nDPId-test PRIVATE "-D_GNU_SOURCE=1" "-DNO_MAIN=1" "-Dsyslog=mock_syslog_stderr")
|
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||||
target_link_libraries(nDPId-test "${STATIC_LIBNDPI_LIB}" "${pkgcfg_lib_NDPI_ndpi}"
|
add_executable(fuzz_ndpi_process_packet test/fuzz_ndpi_process_packet.c)
|
||||||
"${pkgcfg_lib_PCRE_pcre}" "${pkgcfg_lib_MAXMINDDB_maxminddb}"
|
if(BUILD_NDPI)
|
||||||
"${GCRYPT_LIBRARY}" "${PCAP_LIBRARY}"
|
add_dependencies(fuzz_ndpi_process_packet libnDPI)
|
||||||
"-pthread")
|
endif()
|
||||||
|
target_compile_options(fuzz_ndpi_process_packet PRIVATE "-Wno-unused-function" "-fsanitize=fuzzer" "-pthread")
|
||||||
|
target_compile_definitions(fuzz_ndpi_process_packet PRIVATE -D_GNU_SOURCE=1
|
||||||
|
-DPKG_VERSION=\"${PKG_VERSION}\" -DGIT_VERSION=\"${GIT_VERSION}\"
|
||||||
|
${NDPID_DEFS} ${EPOLL_DEFS} ${ZLIB_DEFS} ${PFRING_DEFS})
|
||||||
|
target_include_directories(fuzz_ndpi_process_packet PRIVATE "${STATIC_LIBNDPI_INC}" "${DEFAULT_NDPI_INCLUDE}"
|
||||||
|
${NDPID_DEPS_INC} ${PFRING_KERNEL_INC} ${PFRING_INC})
|
||||||
|
target_link_libraries(fuzz_ndpi_process_packet "${STATIC_LIBNDPI_LIB}" "${STATIC_PFRING_LIB}" "${pkgcfg_lib_PCAP_pcap}" "${pkgcfg_lib_NDPI_ndpi}"
|
||||||
|
"${pkgcfg_lib_PCRE_pcre2-8}" "${pkgcfg_lib_MAXMINDDB_maxminddb}" "${pkgcfg_lib_ZLIB_z}"
|
||||||
|
"${GCRYPT_LIBRARY}" "${GCRYPT_ERROR_LIBRARY}" "${PCAP_LIBRARY}" "${LIBM_LIB}" "${PF_RING_LIB}"
|
||||||
|
"-pthread")
|
||||||
|
target_link_options(fuzz_ndpi_process_packet PRIVATE "-fsanitize=fuzzer")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(BUILD_EXAMPLES)
|
if(BUILD_EXAMPLES)
|
||||||
add_executable(nDPIsrvd-collectd examples/c-collectd/c-collectd.c)
|
add_executable(nDPIsrvd-collectd examples/c-collectd/c-collectd.c utils.c)
|
||||||
target_compile_options(nDPIsrvd-collectd PRIVATE ${MEMORY_PROFILING_CFLAGS})
|
if(BUILD_NDPI)
|
||||||
|
add_dependencies(nDPIsrvd-collectd libnDPI)
|
||||||
|
endif()
|
||||||
|
target_compile_definitions(nDPIsrvd-collectd PRIVATE ${NDPID_DEFS})
|
||||||
target_include_directories(nDPIsrvd-collectd PRIVATE
|
target_include_directories(nDPIsrvd-collectd PRIVATE
|
||||||
"${CMAKE_SOURCE_DIR}"
|
"${STATIC_LIBNDPI_INC}" "${DEFAULT_NDPI_INCLUDE}" "${CMAKE_SOURCE_DIR}" ${NDPID_DEPS_INC})
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies"
|
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies/jsmn"
|
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies/uthash/src")
|
|
||||||
|
|
||||||
add_executable(nDPIsrvd-captured examples/c-captured/c-captured.c utils.c)
|
add_executable(nDPIsrvd-captured examples/c-captured/c-captured.c utils.c)
|
||||||
target_compile_options(nDPIsrvd-captured PRIVATE ${MEMORY_PROFILING_CFLAGS})
|
if(BUILD_NDPI)
|
||||||
|
add_dependencies(nDPIsrvd-captured libnDPI)
|
||||||
|
endif()
|
||||||
|
target_compile_definitions(nDPIsrvd-captured PRIVATE ${NDPID_DEFS})
|
||||||
target_include_directories(nDPIsrvd-captured PRIVATE
|
target_include_directories(nDPIsrvd-captured PRIVATE
|
||||||
"${CMAKE_SOURCE_DIR}"
|
"${STATIC_LIBNDPI_INC}" "${DEFAULT_NDPI_INCLUDE}" "${CMAKE_SOURCE_DIR}" ${NDPID_DEPS_INC})
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies"
|
target_link_libraries(nDPIsrvd-captured "${pkgcfg_lib_PCAP_pcap}" "${pkgcfg_lib_NDPI_ndpi}"
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies/jsmn"
|
"${pkgcfg_lib_PCRE_pcre2-8}" "${pkgcfg_lib_MAXMINDDB_maxminddb}"
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies/uthash/src")
|
"${GCRYPT_LIBRARY}" "${GCRYPT_ERROR_LIBRARY}" "${PCAP_LIBRARY}")
|
||||||
target_link_libraries(nDPIsrvd-captured "${PCAP_LIBRARY}")
|
|
||||||
|
|
||||||
add_executable(nDPIsrvd-json-dump examples/c-json-stdout/c-json-stdout.c)
|
add_executable(nDPIsrvd-analysed examples/c-analysed/c-analysed.c utils.c)
|
||||||
target_include_directories(nDPIsrvd-json-dump PRIVATE
|
if(BUILD_NDPI)
|
||||||
"${CMAKE_SOURCE_DIR}"
|
add_dependencies(nDPIsrvd-analysed libnDPI)
|
||||||
"${CMAKE_SOURCE_DIR}/dependencies/jsmn")
|
endif()
|
||||||
|
target_compile_definitions(nDPIsrvd-analysed PRIVATE ${NDPID_DEFS})
|
||||||
|
target_include_directories(nDPIsrvd-analysed PRIVATE
|
||||||
|
"${STATIC_LIBNDPI_INC}" "${DEFAULT_NDPI_INCLUDE}" "${CMAKE_SOURCE_DIR}" ${NDPID_DEPS_INC})
|
||||||
|
|
||||||
install(TARGETS nDPIsrvd-collectd nDPIsrvd-captured nDPIsrvd-json-dump DESTINATION bin)
|
add_executable(nDPIsrvd-simple examples/c-simple/c-simple.c)
|
||||||
|
target_compile_definitions(nDPIsrvd-simple PRIVATE ${NDPID_DEFS})
|
||||||
|
target_include_directories(nDPIsrvd-simple PRIVATE ${NDPID_DEPS_INC})
|
||||||
|
|
||||||
|
if(ENABLE_COVERAGE)
|
||||||
|
add_dependencies(coverage nDPIsrvd-analysed nDPIsrvd-collectd nDPIsrvd-captured nDPIsrvd-simple)
|
||||||
|
if(BUILD_NDPI)
|
||||||
|
add_dependencies(coverage libnDPI)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_DBUS)
|
||||||
|
add_executable(nDPIsrvd-notifyd examples/c-notifyd/c-notifyd.c utils.c)
|
||||||
|
if(BUILD_NDPI)
|
||||||
|
add_dependencies(nDPIsrvd-notifyd libnDPI)
|
||||||
|
endif()
|
||||||
|
target_compile_definitions(nDPIsrvd-notifyd PRIVATE ${NDPID_DEFS})
|
||||||
|
target_include_directories(nDPIsrvd-notifyd PRIVATE
|
||||||
|
"${STATIC_LIBNDPI_INC}" "${DEFAULT_NDPI_INCLUDE}" "${CMAKE_SOURCE_DIR}" "${NDPID_DEPS_INC}"
|
||||||
|
"${DBUS_INCLUDE_DIRS}")
|
||||||
|
target_link_libraries(nDPIsrvd-notifyd "${DBUS_LIBRARIES}")
|
||||||
|
install(TARGETS nDPIsrvd-notifyd DESTINATION bin)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_CURL)
|
||||||
|
add_executable(nDPIsrvd-influxd examples/c-influxd/c-influxd.c utils.c)
|
||||||
|
if(BUILD_NDPI)
|
||||||
|
add_dependencies(nDPIsrvd-influxd libnDPI)
|
||||||
|
endif()
|
||||||
|
target_compile_definitions(nDPIsrvd-influxd PRIVATE ${NDPID_DEFS})
|
||||||
|
target_include_directories(nDPIsrvd-influxd PRIVATE
|
||||||
|
"${STATIC_LIBNDPI_INC}" "${DEFAULT_NDPI_INCLUDE}" "${CMAKE_SOURCE_DIR}" "${NDPID_DEPS_INC}"
|
||||||
|
"${CURL_INCLUDE_DIRS}")
|
||||||
|
target_link_libraries(nDPIsrvd-influxd "${CURL_LIBRARIES}")
|
||||||
|
install(TARGETS nDPIsrvd-influxd DESTINATION bin)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(TARGETS nDPIsrvd-analysed nDPIsrvd-collectd nDPIsrvd-captured nDPIsrvd-simple DESTINATION bin)
|
||||||
|
install(FILES examples/c-collectd/plugin_nDPIsrvd.conf examples/c-collectd/rrdgraph.sh DESTINATION share/nDPId/nDPIsrvd-collectd)
|
||||||
|
install(DIRECTORY examples/c-collectd/www DESTINATION share/nDPId/nDPIsrvd-collectd)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_RUST_EXAMPLES)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/target/release/rs-simple
|
||||||
|
COMMAND cargo build --release
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples/rs-simple
|
||||||
|
COMMENT "Build Rust executable with cargo: rs-simple"
|
||||||
|
)
|
||||||
|
add_custom_target(rs-simple ALL
|
||||||
|
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/target/release/rs-simple
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_SYSTEMD)
|
||||||
|
configure_file(packages/systemd/ndpisrvd.service.in ndpisrvd.service @ONLY)
|
||||||
|
configure_file(packages/systemd/ndpid@.service.in ndpid@.service @ONLY)
|
||||||
|
|
||||||
|
install(DIRECTORY DESTINATION etc/nDPId)
|
||||||
|
install(FILES "ndpid.conf.example" DESTINATION share/nDPId)
|
||||||
|
install(FILES "ndpisrvd.conf.example" DESTINATION share/nDPId)
|
||||||
|
install(FILES "${CMAKE_BINARY_DIR}/ndpisrvd.service" DESTINATION lib/systemd/system)
|
||||||
|
install(FILES "${CMAKE_BINARY_DIR}/ndpid@.service" DESTINATION lib/systemd/system)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(FILES config.h
|
||||||
|
dependencies/nDPIsrvd.h
|
||||||
|
dependencies/jsmn/jsmn.h
|
||||||
|
dependencies/uthash/src/utarray.h
|
||||||
|
dependencies/uthash/src/uthash.h
|
||||||
|
dependencies/uthash/src/utlist.h
|
||||||
|
dependencies/uthash/src/utringbuffer.h
|
||||||
|
dependencies/uthash/src/utstack.h
|
||||||
|
dependencies/uthash/src/utstring.h
|
||||||
|
DESTINATION include/nDPId)
|
||||||
install(TARGETS nDPId DESTINATION sbin)
|
install(TARGETS nDPId DESTINATION sbin)
|
||||||
install(TARGETS nDPIsrvd nDPId-test DESTINATION bin)
|
install(TARGETS nDPIsrvd nDPId-test DESTINATION bin)
|
||||||
install(FILES dependencies/nDPIsrvd.py DESTINATION share/nDPId)
|
if(BUILD_EXAMPLES)
|
||||||
install(FILES examples/py-flow-info/flow-info.py DESTINATION bin RENAME nDPIsrvd-flow-info.py)
|
install(FILES dependencies/nDPIsrvd.py
|
||||||
|
DESTINATION share/nDPId)
|
||||||
|
install(FILES examples/py-flow-info/flow-info.py
|
||||||
|
DESTINATION bin RENAME nDPIsrvd-flow-info.py
|
||||||
|
PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||||
|
install(FILES examples/py-json-stdout/json-stdout.py
|
||||||
|
DESTINATION bin RENAME nDPIsrvd-json-stdout.py
|
||||||
|
PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||||
|
install(FILES examples/py-schema-validation/py-schema-validation.py
|
||||||
|
DESTINATION bin RENAME nDPIsrvd-schema-validation.py
|
||||||
|
PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||||
|
install(FILES examples/py-semantic-validation/py-semantic-validation.py
|
||||||
|
DESTINATION bin RENAME nDPIsrvd-semantic-validation.py
|
||||||
|
PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||||
|
install(FILES examples/py-machine-learning/sklearn-random-forest.py
|
||||||
|
DESTINATION bin RENAME nDPIsrvd-sklearn.py
|
||||||
|
PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||||
|
endif()
|
||||||
|
install(FILES schema/error_event_schema.json schema/daemon_event_schema.json
|
||||||
|
schema/flow_event_schema.json schema/packet_event_schema.json DESTINATION share/nDPId/json-schema)
|
||||||
|
|
||||||
message(STATUS "--------------------------")
|
message(STATUS "--------------------------")
|
||||||
|
message(STATUS "nDPId GIT_VERSION........: ${GIT_VERSION}")
|
||||||
|
message(STATUS "Cross Compilation........: ${CMAKE_CROSSCOMPILING}")
|
||||||
message(STATUS "CMAKE_BUILD_TYPE.........: ${CMAKE_BUILD_TYPE}")
|
message(STATUS "CMAKE_BUILD_TYPE.........: ${CMAKE_BUILD_TYPE}")
|
||||||
message(STATUS "CMAKE_C_FLAGS............: ${CMAKE_C_FLAGS}")
|
message(STATUS "CMAKE_C_FLAGS............: ${CMAKE_C_FLAGS}")
|
||||||
if(ENABLE_MEMORY_PROFILING)
|
message(STATUS "NDPID_DEFS...............: ${NDPID_DEFS}")
|
||||||
message(STATUS "MEMORY_PROFILING_CFLAGS..: ${MEMORY_PROFILING_CFLAGS}")
|
message(STATUS "FORCE_POLL...............: ${FORCE_POLL}")
|
||||||
|
message(STATUS "ENABLE_PFRING............: ${ENABLE_PFRING}")
|
||||||
|
if(ENABLE_PFRING)
|
||||||
|
message(STATUS "PFRING_LINK_STATIC.......: ${PFRING_LINK_STATIC}")
|
||||||
endif()
|
endif()
|
||||||
|
message(STATUS "ENABLE_CRYPTO............: ${ENABLE_CRYPTO}")
|
||||||
|
message(STATUS "ENABLE_COVERAGE..........: ${ENABLE_COVERAGE}")
|
||||||
message(STATUS "ENABLE_SANITIZER.........: ${ENABLE_SANITIZER}")
|
message(STATUS "ENABLE_SANITIZER.........: ${ENABLE_SANITIZER}")
|
||||||
message(STATUS "ENABLE_SANITIZER_THREAD..: ${ENABLE_SANITIZER_THREAD}")
|
message(STATUS "ENABLE_SANITIZER_THREAD..: ${ENABLE_SANITIZER_THREAD}")
|
||||||
message(STATUS "ENABLE_MEMORY_PROFILING..: ${ENABLE_MEMORY_PROFILING}")
|
message(STATUS "ENABLE_MEMORY_PROFILING..: ${ENABLE_MEMORY_PROFILING}")
|
||||||
if(NOT BUILD_NDPI AND NOT STATIC_LIBNDPI_INSTALLDIR STREQUAL "")
|
message(STATUS "ENABLE_ZLIB..............: ${ENABLE_ZLIB}")
|
||||||
|
message(STATUS "BUILD_NDPI...............: ${BUILD_NDPI}")
|
||||||
|
message(STATUS "BUILD_EXAMPLES...........: ${BUILD_EXAMPLES}")
|
||||||
|
message(STATUS "BUILD_RUST_EXAMPLES......: ${BUILD_RUST_EXAMPLES}")
|
||||||
|
if(BUILD_EXAMPLES)
|
||||||
|
message(STATUS "ENABLE_DBUS..............: ${ENABLE_DBUS}")
|
||||||
|
message(STATUS "ENABLE_CURL..............: ${ENABLE_CURL}")
|
||||||
|
endif()
|
||||||
|
if(BUILD_NDPI)
|
||||||
|
message(STATUS "NDPI_ADDITIONAL_ARGS.....: ${NDPI_ADDITIONAL_ARGS}")
|
||||||
|
endif()
|
||||||
|
message(STATUS "NDPI_NO_PKGCONFIG........: ${NDPI_NO_PKGCONFIG}")
|
||||||
|
message(STATUS "--------------------------")
|
||||||
|
if(PFRING_INSTALLDIR)
|
||||||
|
message(STATUS "PFRING_INSTALLDIR........: ${PFRING_INSTALLDIR}")
|
||||||
|
message(STATUS "- PFRING_INC.............: ${PFRING_INC}")
|
||||||
|
message(STATUS "- PFRING_KERNEL_INC......: ${PFRING_KERNEL_INC}")
|
||||||
|
message(STATUS "- STATIC_PFRING_LIB......: ${STATIC_PFRING_LIB}")
|
||||||
|
message(STATUS "- SHARED_PFRING_LIB......: ${PF_RING_LIB}")
|
||||||
|
message(STATUS "--------------------------")
|
||||||
|
endif()
|
||||||
|
if(STATIC_LIBNDPI_INSTALLDIR)
|
||||||
message(STATUS "STATIC_LIBNDPI_INSTALLDIR: ${STATIC_LIBNDPI_INSTALLDIR}")
|
message(STATUS "STATIC_LIBNDPI_INSTALLDIR: ${STATIC_LIBNDPI_INSTALLDIR}")
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "BUILD_NDPI...............: ${BUILD_NDPI}")
|
if(STATIC_LIBNDPI_INSTALLDIR OR BUILD_NDPI OR NDPI_NO_PKGCONFIG)
|
||||||
message(STATUS "NDPI_NO_PKGCONFIG........: ${NDPI_NO_PKGCONFIG}")
|
message(STATUS "- STATIC_LIBNDPI_INC.....: ${STATIC_LIBNDPI_INC}")
|
||||||
if(NDPI_NO_PKGCONFIG)
|
message(STATUS "- STATIC_LIBNDPI_LIB.....: ${STATIC_LIBNDPI_LIB}")
|
||||||
message(STATUS "LIBNDPI_INC..............: ${LIBNDPI_INC}")
|
message(STATUS "- NDPI_WITH_GCRYPT.......: ${NDPI_WITH_GCRYPT}")
|
||||||
message(STATUS "LIBNDPI_LIB..............: ${LIBNDPI_LIB}")
|
message(STATUS "- NDPI_WITH_PCRE.........: ${NDPI_WITH_PCRE}")
|
||||||
|
message(STATUS "- NDPI_WITH_MAXMINDDB....: ${NDPI_WITH_MAXMINDDB}")
|
||||||
endif()
|
endif()
|
||||||
if(NOT STATIC_LIBNDPI_INSTALLDIR STREQUAL "" OR BUILD_NDPI OR NDPI_NO_PKGCONFIG)
|
if(NOT STATIC_LIBNDPI_INSTALLDIR AND NOT BUILD_NDPI)
|
||||||
message(STATUS "--------------------------")
|
message(STATUS "- DEFAULT_NDPI_INCLUDE...: ${DEFAULT_NDPI_INCLUDE}")
|
||||||
message(STATUS "- STATIC_LIBNDPI_INC....: ${STATIC_LIBNDPI_INC}")
|
endif()
|
||||||
message(STATUS "- STATIC_LIBNDPI_LIB....: ${STATIC_LIBNDPI_LIB}")
|
if(NOT NDPI_NO_PKGCONFIG)
|
||||||
message(STATUS "- NDPI_WITH_GCRYPT......: ${NDPI_WITH_GCRYPT}")
|
message(STATUS "- pkgcfg_lib_NDPI_ndpi...: ${pkgcfg_lib_NDPI_ndpi}")
|
||||||
message(STATUS "- NDPI_WITH_PCRE........: ${NDPI_WITH_PCRE}")
|
|
||||||
message(STATUS "- NDPI_WITH_MAXMINDDB...: ${NDPI_WITH_MAXMINDDB}")
|
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "--------------------------")
|
message(STATUS "--------------------------")
|
||||||
|
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||||
|
message(STATUS "Fuzzing enabled")
|
||||||
|
endif()
|
||||||
|
|||||||
46
Dockerfile
Normal file
46
Dockerfile
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
FROM ubuntu:22.04 AS builder-ubuntu-2204
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
RUN apt-get -y update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
autoconf automake build-essential ca-certificates cmake git \
|
||||||
|
libpcap-dev libcurl4-openssl-dev libdbus-1-dev libtool make pkg-config unzip wget \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& git clone https://github.com/utoni/nDPId.git
|
||||||
|
|
||||||
|
WORKDIR /root/nDPId
|
||||||
|
RUN cmake -S . -B build -DBUILD_NDPI=ON -DBUILD_EXAMPLES=ON \
|
||||||
|
-DENABLE_DBUS=ON -DENABLE_CURL=ON \
|
||||||
|
&& cmake --build build --verbose
|
||||||
|
|
||||||
|
FROM ubuntu:22.04
|
||||||
|
USER root
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
COPY --from=builder-ubuntu-2204 /root/nDPId/build/nDPId /usr/sbin/nDPId
|
||||||
|
COPY --from=builder-ubuntu-2204 /root/nDPId/build/nDPIsrvd /usr/bin/nDPIsrvd
|
||||||
|
COPY --from=builder-ubuntu-2204 /root/nDPId/build/nDPId-test /usr/bin/nDPId-test
|
||||||
|
COPY --from=builder-ubuntu-2204 /root/nDPId/build/nDPIsrvd-collectd /usr/bin/nDPIsrvd-collectd
|
||||||
|
COPY --from=builder-ubuntu-2204 /root/nDPId/build/nDPIsrvd-captured /usr/bin/nDPIsrvd-captured
|
||||||
|
COPY --from=builder-ubuntu-2204 /root/nDPId/build/nDPIsrvd-analysed /usr/bin/nDPIsrvd-anaylsed
|
||||||
|
COPY --from=builder-ubuntu-2204 /root/nDPId/build/nDPIsrvd-analysed /usr/bin/nDPIsrvd-anaylsed
|
||||||
|
COPY --from=builder-ubuntu-2204 /root/nDPId/build/nDPIsrvd-notifyd /usr/bin/nDPIsrvd-notifyd
|
||||||
|
COPY --from=builder-ubuntu-2204 /root/nDPId/build/nDPIsrvd-influxd /usr/bin/nDPIsrvd-influxd
|
||||||
|
COPY --from=builder-ubuntu-2204 /root/nDPId/build/nDPIsrvd-simple /usr/bin/nDPIsrvd-simple
|
||||||
|
|
||||||
|
RUN apt-get -y update \
|
||||||
|
&& apt-get install -y --no-install-recommends libpcap-dev \
|
||||||
|
&& apt-get clean
|
||||||
|
|
||||||
|
USER nobody
|
||||||
|
RUN /usr/bin/nDPIsrvd -h || { RC=$?; test ${RC} -eq 1; }; \
|
||||||
|
/usr/sbin/nDPId -h || { RC=$?; test ${RC} -eq 1; }
|
||||||
|
|
||||||
|
FROM archlinux:base-devel AS builder-archlinux
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
RUN pacman --noconfirm -Sy cmake git unzip wget && mkdir /build && chown nobody /build && cd /build \
|
||||||
|
&& runuser -u nobody git clone https://github.com/utoni/nDPId.git
|
||||||
|
|
||||||
|
WORKDIR /build/nDPId/packages/archlinux
|
||||||
|
RUN runuser -u nobody makepkg
|
||||||
332
README.md
332
README.md
@@ -1,67 +1,188 @@
|
|||||||
# abstract
|
[](https://github.com/utoni/nDPId/actions/workflows/build.yml)
|
||||||
|
[](https://gitlab.com/utoni/nDPId/-/pipelines)
|
||||||
|
[](https://app.circleci.com/pipelines/github/utoni/nDPId)
|
||||||
|
[](https://sonarcloud.io/summary/new_code?id=lnslbrty_nDPId)
|
||||||
|
[](https://sonarcloud.io/summary/new_code?id=lnslbrty_nDPId)
|
||||||
|
[](https://sonarcloud.io/summary/new_code?id=lnslbrty_nDPId)
|
||||||
|
[](https://sonarcloud.io/summary/new_code?id=lnslbrty_nDPId)
|
||||||
|
[](https://sonarcloud.io/summary/new_code?id=lnslbrty_nDPId)
|
||||||
|
[](https://sonarcloud.io/summary/new_code?id=lnslbrty_nDPId)
|
||||||
|

|
||||||
|
|
||||||
nDPId is a set of daemons and tools to capture, process and classify network flows.
|
# References
|
||||||
It's only dependencies (besides a half-way modern c library and POSIX threads) are libnDPI (>= 3.6.0 or current github dev branch) and libpcap.
|
|
||||||
|
|
||||||
The core daemon nDPId uses pthread but does use mutexes for performance reasons.
|
[ntop Webinar 2022](https://www.ntop.org/webinar/ntop-webinar-on-dec-14th-community-meeting-and-future-plans/)
|
||||||
Instead synchronization is achieved by a packet distribution mechanism.
|
[ntopconf 2023](https://www.ntop.org/ntopconf2023/)
|
||||||
To balance all workload to all threads (more or less) equally a hash value is calculated using the 5-tuple.
|
|
||||||
This value serves as unique identifier for the processing thread. Multithreaded packet processing has to be flow-stable.
|
|
||||||
|
|
||||||
nDPId uses libnDPI's JSON serialization to produce meaningful JSON output which it then sends to the nDPIsrvd for distribution.
|
# Disclaimer
|
||||||
High level applications can connect to nDPIsrvd to get the latest flow/packet events from nDPId.
|
|
||||||
|
|
||||||
Unfortunately nDPIsrvd does currently not support any encryption/authentication for TCP connections.
|
Please respect & protect the privacy of others.
|
||||||
|
|
||||||
# architecture
|
The purpose of this software is not to spy on others, but to detect network anomalies and malicious traffic.
|
||||||
|
|
||||||
This project uses some kind of microservice architecture.
|
# Abstract
|
||||||
|
|
||||||
|
nDPId is a set of daemons and tools to capture, process and classify network traffic.
|
||||||
|
Its minimal dependencies (besides a to some extent modern C library and POSIX threads) are libnDPI (>=5.0.0 or current github dev branch) and libpcap.
|
||||||
|
|
||||||
|
The daemon `nDPId` is capable of multithreading for packet processing, but w/o mutexes for performance reasons.
|
||||||
|
Instead, synchronization is achieved by a packet distribution mechanism.
|
||||||
|
To balance the workload to all threads (more or less) equally, a unique identifier represented as hash value is calculated using a 3-tuple consisting of: IPv4/IPv6 src/dst address; IP header value of the layer4 protocol; and (for TCP/UDP) src/dst port. Other protocols e.g. ICMP/ICMPv6 lack relevance for DPI, thus nDPId does not distinguish between different ICMP/ICMPv6 flows coming from the same host. This saves memory and performance, but might change in the future.
|
||||||
|
|
||||||
|
`nDPId` uses libnDPI's JSON serialization interface to generate a JSON messages for each event it receives from the library and which it then sends out to a UNIX-socket (default: `/tmp/ndpid-collector.sock` ). From such a socket, `nDPIsrvd` (or other custom applications) can retrieve incoming JSON-messages and further proceed working/distributing messages to higher-level applications.
|
||||||
|
|
||||||
|
Unfortunately, `nDPIsrvd` does not yet support any encryption/authentication for TCP connections (TODO!).
|
||||||
|
|
||||||
|
# Architecture
|
||||||
|
|
||||||
|
This project uses a kind of microservice architecture.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
_______________________ __________________________
|
connect to UNIX socket [1] connect to UNIX/TCP socket [2]
|
||||||
| "producer" | | "consumer" |
|
_______________________ | | __________________________
|
||||||
|
| "producer" |___| |___| "consumer" |
|
||||||
|---------------------| _____________________________ |------------------------|
|
|---------------------| _____________________________ |------------------------|
|
||||||
| | | nDPIsrvd | | |
|
| | | nDPIsrvd | | |
|
||||||
| nDPId --- Thread 1 >| ---> |> | <| <--- |< example/c-json-stdout |
|
| nDPId --- Thread 1 >| ---> |> | <| ---> |< example/c-json-stdout |
|
||||||
| (eth0) `- Thread 2 >| ---> |> collector | distributor <| <--- |________________________|
|
| (eth0) `- Thread 2 >| ---> |> collector | distributor <| ---> |________________________|
|
||||||
| `- Thread N >| ---> |> >>> forward >>> <| <--- | |
|
| `- Thread N >| ---> |> >>> forward >>> <| ---> | |
|
||||||
|_____________________| ^ |____________|______________| ^ |< example/py-flow-info |
|
|_____________________| ^ |____________|______________| ^ |< example/py-flow-info |
|
||||||
| | | | |________________________|
|
| | | | |________________________|
|
||||||
| nDPId --- Thread 1 >| `- connect to UNIX socket | | |
|
| nDPId --- Thread 1 >| `- send serialized data [1] | | |
|
||||||
| (eth1) `- Thread 2 >| `- sends serialized data | |< example/... |
|
| (eth1) `- Thread 2 >| | |< example/... |
|
||||||
| `- Thread N >| | |________________________|
|
| `- Thread N >| receive serialized data [2] -' |________________________|
|
||||||
|_____________________| |
|
|_____________________|
|
||||||
`- connect to UNIX/TCP socket
|
|
||||||
`- receives serialized data
|
|
||||||
```
|
```
|
||||||
|
where:
|
||||||
|
|
||||||
It doesn't use a producer/consumer design pattern, so the wording is not precise.
|
* `nDPId` capture traffic, extract traffic data (with libnDPI) and send a JSON-serialized output stream to an already existing UNIX-socket;
|
||||||
|
* `nDPIsrvd`:
|
||||||
|
|
||||||
# JSON TCP protocol
|
* create and manage an "incoming" UNIX-socket (ref [1] above), to fetch data from a local `nDPId`;
|
||||||
|
* apply a buffering logic to received data;
|
||||||
|
* create and manage an "outgoing" UNIX or TCP socket (ref [2] above) to relay matched events
|
||||||
|
to connected clients
|
||||||
|
|
||||||
All JSON strings sent need to be in the following format:
|
* `consumers` are common/custom applications being able to receive selected flows/events, via both UNIX-socket or TCP-socket.
|
||||||
```text
|
|
||||||
[5-digit-number][JSON string]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example:
|
|
||||||
|
# JSON stream format
|
||||||
|
|
||||||
|
JSON messages streamed by both `nDPId` and `nDPIsrvd` are presented with:
|
||||||
|
|
||||||
|
* a 5-digit-number describing (as decimal number) the **entire** JSON message including the newline `\n` at the end;
|
||||||
|
* the JSON messages
|
||||||
|
|
||||||
```text
|
```text
|
||||||
00015{"key":"value"}
|
[5-digit-number][JSON message]
|
||||||
```
|
```
|
||||||
where `00015` describes the length of a **complete** JSON string.
|
|
||||||
|
|
||||||
TODO: Describe data format via JSON schema.
|
as with the following example:
|
||||||
|
|
||||||
# build (CMake)
|
```text
|
||||||
|
01223{"flow_event_id":7,"flow_event_name":"detection-update","thread_id":12,"packet_id":307,"source":"wlan0", ...snip...}
|
||||||
|
00458{"packet_event_id":2,"packet_event_name":"packet-flow","thread_id":11,"packet_id":324,"source":"wlan0", ...snip...}
|
||||||
|
00572{"flow_event_id":1,"flow_event_name":"new","thread_id":11,"packet_id":324,"source":"wlan0", ...snip...}
|
||||||
|
```
|
||||||
|
|
||||||
|
The full stream of `nDPId` generated JSON-events can be retrieved directly from `nDPId`, without relying on `nDPIsrvd`, by providing a properly managed UNIX-socket.
|
||||||
|
|
||||||
|
Technical details about the JSON-message format can be obtained from the related `.schema` file included in the `schema` directory
|
||||||
|
|
||||||
|
|
||||||
|
# Events
|
||||||
|
|
||||||
|
`nDPId` generates JSON messages whereby each string is assigned to a certain event.
|
||||||
|
Those events specify the contents (key-value-pairs) of the JSON message.
|
||||||
|
They are divided into four categories, each with a number of subevents.
|
||||||
|
|
||||||
|
## Error Events
|
||||||
|
They are 17 distinct events, indicating that layer2 or layer3 packet processing failed or not enough flow memory available:
|
||||||
|
|
||||||
|
1. Unknown datalink layer packet
|
||||||
|
2. Unknown L3 protocol
|
||||||
|
3. Unsupported datalink layer
|
||||||
|
4. Packet too short
|
||||||
|
5. Unknown packet type
|
||||||
|
6. Packet header invalid
|
||||||
|
7. IP4 packet too short
|
||||||
|
8. Packet smaller than IP4 header:
|
||||||
|
9. nDPI IPv4/L4 payload detection failed
|
||||||
|
10. IP6 packet too short
|
||||||
|
11. Packet smaller than IP6 header
|
||||||
|
12. nDPI IPv6/L4 payload detection failed
|
||||||
|
13. TCP packet smaller than expected
|
||||||
|
14. UDP packet smaller than expected
|
||||||
|
15. Captured packet size is smaller than expected packet size
|
||||||
|
16. Max flows to track reached
|
||||||
|
17. Flow memory allocation failed
|
||||||
|
|
||||||
|
Detailed JSON-schema is available [here](schema/error_event_schema.json)
|
||||||
|
|
||||||
|
## Daemon Events
|
||||||
|
There are 4 distinct events indicating startup/shutdown or status events as well as a reconnect event if there was a previous connection failure (collector):
|
||||||
|
|
||||||
|
1. init: `nDPId` startup
|
||||||
|
2. reconnect: (UNIX) socket connection lost previously and was established again
|
||||||
|
3. shutdown: `nDPId` terminates gracefully
|
||||||
|
4. status: statistics about the daemon itself e.g. memory consumption, zLib compressions (if enabled)
|
||||||
|
|
||||||
|
Detailed JSON-schema is available [here](schema/daemon_event_schema.json)
|
||||||
|
|
||||||
|
|
||||||
|
## Packet Events
|
||||||
|
There are 2 events containing base64 encoded packet payloads either belonging to a flow or not:
|
||||||
|
|
||||||
|
1. packet: does not belong to any flow
|
||||||
|
2. packet-flow: belongs to a flow e.g. TCP/UDP or ICMP
|
||||||
|
|
||||||
|
Detailed JSON-schema is available [here](schema/packet_event_schema.json)
|
||||||
|
|
||||||
|
## Flow Events
|
||||||
|
There are 9 distinct events related to a flow:
|
||||||
|
|
||||||
|
1. new: a new TCP/UDP/ICMP flow seen which will be tracked
|
||||||
|
2. end: a TCP connection terminates
|
||||||
|
3. idle: a flow timed out, because there was no packet on the wire for a certain amount of time
|
||||||
|
4. update: inform nDPIsrvd or other apps about a long-lasting flow, whose detection was finished a long time ago but is still active
|
||||||
|
5. analyse: provide some information about extracted features of a flow (Experimental; disabled per default, enable with `-A`)
|
||||||
|
6. guessed: `libnDPI` was not able to reliably detect a layer7 protocol and falls back to IP/Port based detection
|
||||||
|
7. detected: `libnDPI` sucessfully detected a layer7 protocol
|
||||||
|
8. detection-update: `libnDPI` dissected more layer7 protocol data (after detection already done)
|
||||||
|
9. not-detected: neither detected nor guessed
|
||||||
|
|
||||||
|
Detailed JSON-schema is available [here](schema/flow_event_schema.json). Also, a graphical representation of *Flow Events* timeline is available [here](schema/flow_events_diagram.png).
|
||||||
|
|
||||||
|
# Flow States
|
||||||
|
|
||||||
|
A flow can have three different states while it is been tracked by `nDPId`.
|
||||||
|
|
||||||
|
1. skipped: the flow will be tracked, but no detection will happen to reduce memory usage.
|
||||||
|
See command line argument `-I` and `-E`
|
||||||
|
2. finished: detection finished and the memory used for the detection is freed
|
||||||
|
3. info: detection is in progress and all flow memory required for `libnDPI` is allocated (this state consumes most memory)
|
||||||
|
|
||||||
|
# Build (CMake)
|
||||||
|
|
||||||
|
`nDPId` build system is based on [CMake](https://cmake.org/)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
git clone https://github.com/utoni/nDPId.git
|
||||||
|
[...]
|
||||||
|
cd ndpid
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
|
[...]
|
||||||
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
see below for a full/test live-session
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Based on your build environment and/or desiderata, you could need:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
mkdir build
|
mkdir build
|
||||||
@@ -72,38 +193,78 @@ ccmake ..
|
|||||||
or to build with a staticially linked libnDPI:
|
or to build with a staticially linked libnDPI:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
mkdir build
|
cmake -S . -B ./build \
|
||||||
cd build
|
-DSTATIC_LIBNDPI_INSTALLDIR=[path/to/your/libnDPI/installdir] \
|
||||||
cmake .. -DSTATIC_LIBNDPI_INSTALLDIR=[path/to/your/libnDPI/installdir]
|
-DNDPI_NO_PKGCONFIG=ON
|
||||||
|
cmake --build ./build
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're using the latter one, make sure that you've configured libnDPI with `./configure --prefix=[path/to/your/libnDPI/installdir]`
|
If you use the latter, make sure that you've configured libnDPI with `./configure --prefix=[path/to/your/libnDPI/installdir]`
|
||||||
and do not forget to set the all necessary CMake variables to link against shared libraries used by your nDPI build.
|
and remember to set the all-necessary CMake variables to link against shared libraries used by your nDPI build.
|
||||||
|
You'll also need to use `-DNDPI_NO_PKGCONFIG=ON` if `STATIC_LIBNDPI_INSTALLDIR` does not contain a pkg-config file.
|
||||||
|
|
||||||
e.g.:
|
e.g.:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
mkdir build
|
cmake -S . -B ./build \
|
||||||
cd build
|
-DSTATIC_LIBNDPI_INSTALLDIR=[path/to/your/libnDPI/installdir] \
|
||||||
cmake .. -DSTATIC_LIBNDPI_INSTALLDIR=[path/to/your/libnDPI/installdir] -DNDPI_WITH_GCRYPT=ON -DNDPI_WITH_PCRE=OFF -DNDPI_WITH_MAXMINDDB=OFF
|
-DNDPI_NO_PKGCONFIG=ON \
|
||||||
|
-DNDPI_WITH_GCRYPT=ON -DNDPI_WITH_PCRE=OFF -DNDPI_WITH_MAXMINDDB=OFF
|
||||||
|
cmake --build ./build
|
||||||
```
|
```
|
||||||
|
|
||||||
Or if this is all too much for you, let CMake do it for you:
|
Or let a shell script do the work for you:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
mkdir build
|
cmake -S . -B ./build \
|
||||||
cd build
|
-DBUILD_NDPI=ON
|
||||||
cmake .. -DBUILD_NDPI=ON
|
cmake --build ./build
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The CMake cache variable `-DBUILD_NDPI=ON` builds a version of `libnDPI` residing as a git submodule in this repository.
|
||||||
|
|
||||||
# run
|
# run
|
||||||
|
|
||||||
Generate a nDPId compatible JSON dump:
|
As mentioned above, in order to run `nDPId`, a UNIX-socket needs to be provided in order to stream our related JSON-data.
|
||||||
|
|
||||||
|
Such a UNIX-socket can be provided by both the included `nDPIsrvd` daemon, or, if you simply need a quick check, with the [ncat](https://nmap.org/book/ncat-man.html) utility, with a simple `ncat -U /tmp/listen.sock -l -k`. Remember that OpenBSD `netcat` is not able to handle multiple connections reliably.
|
||||||
|
|
||||||
|
Once the socket is ready, you can run `nDPId` capturing and analyzing your own traffic, with something similar to: `sudo nDPId -c /tmp/listen.sock`
|
||||||
|
If you're using OpenBSD `netcat`, you need to run: `sudo nDPId -c /tmp/listen.sock -o max-reader-threads=1`
|
||||||
|
Make sure that the UNIX socket is accessible by the user (see -u) to whom nDPId changes to, default: nobody.
|
||||||
|
|
||||||
|
Of course, both `ncat` and `nDPId` need to point to the same UNIX-socket (`nDPId` provides the `-c` option, exactly for this. By default, `nDPId` refers to `/tmp/ndpid-collector.sock`, and the same default-path is also used by `nDPIsrvd` for the incoming socket).
|
||||||
|
|
||||||
|
Give `nDPId` some real-traffic. You can capture your own traffic, with something similar to:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
socat -u UNIX-Listen:/tmp/listen.sock,fork - # does the same as `ncat`
|
||||||
|
sudo chown nobody:nobody /tmp/listen.sock # default `nDPId` user/group, see `-u` and `-g`
|
||||||
|
sudo ./nDPId -c /tmp/listen.sock -l
|
||||||
|
```
|
||||||
|
|
||||||
|
`nDPId` supports also UDP collector endpoints:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
nc -d -u 127.0.0.1 7000 -l -k
|
||||||
|
sudo ./nDPId -c 127.0.0.1:7000 -l
|
||||||
|
```
|
||||||
|
|
||||||
|
or you can generate a nDPId-compatible JSON dump with:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./nDPId-test [path-to-a-PCAP-file]
|
./nDPId-test [path-to-a-PCAP-file]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can also automatically fire both `nDPId` and `nDPIsrvd` automatically, with:
|
||||||
|
|
||||||
Daemons:
|
Daemons:
|
||||||
|
```shell
|
||||||
|
make -C [path-to-a-build-dir] daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
Or a manual approach with:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./nDPIsrvd -d
|
./nDPIsrvd -d
|
||||||
sudo ./nDPId -d
|
sudo ./nDPId -d
|
||||||
@@ -120,32 +281,69 @@ And why not a flow-info example?
|
|||||||
./examples/py-flow-info/flow-info.py
|
./examples/py-flow-info/flow-info.py
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
|
||||||
```shell
|
|
||||||
./nDPIsrvd-json-dump
|
|
||||||
```
|
|
||||||
|
|
||||||
or anything below `./examples`.
|
or anything below `./examples`.
|
||||||
|
|
||||||
|
# nDPId tuning
|
||||||
|
|
||||||
|
It is possible to change `nDPId` internals w/o recompiling by using `-o subopt=value`.
|
||||||
|
But be careful: changing the default values may render `nDPId` useless and is not well tested.
|
||||||
|
|
||||||
|
Suboptions for `-o`:
|
||||||
|
|
||||||
|
Format: `subopt` (unit, comment): description
|
||||||
|
|
||||||
|
* `max-flows-per-thread` (N, caution advised): affects max. memory usage
|
||||||
|
* `max-idle-flows-per-thread` (N, safe): max. allowed idle flows whose memory gets freed after `flow-scan-interval`
|
||||||
|
* `max-reader-threads` (N, safe): amount of packet processing threads, every thread can have a max. of `max-flows-per-thread` flows
|
||||||
|
* `daemon-status-interval` (ms, safe): specifies how often daemon event `status` is generated
|
||||||
|
* `compression-scan-interval` (ms, untested): specifies how often `nDPId` scans for inactive flows ready for compression
|
||||||
|
* `compression-flow-inactivity` (ms, untested): the shortest period of time elapsed before `nDPId` considers compressing a flow (e.g. nDPI flow struct) that neither sent nor received any data
|
||||||
|
* `flow-scan-interval` (ms, safe): min. amount of time after which `nDPId` scans for idle or long-lasting flows
|
||||||
|
* `generic-max-idle-time` (ms, untested): time after which a non TCP/UDP/ICMP flow times out
|
||||||
|
* `icmp-max-idle-time` (ms, untested): time after which an ICMP flow times out
|
||||||
|
* `udp-max-idle-time` (ms, caution advised): time after which an UDP flow times out
|
||||||
|
* `tcp-max-idle-time` (ms, caution advised): time after which a TCP flow times out
|
||||||
|
* `tcp-max-post-end-flow-time` (ms, caution advised): a TCP flow that received a FIN or RST waits this amount of time before flow tracking stops and the flow memory is freed
|
||||||
|
* `max-packets-per-flow-to-send` (N, safe): max. `packet-flow` events generated for the first N packets of each flow
|
||||||
|
* `max-packets-per-flow-to-process` (N, caution advised): max. amount of packets processed by `libnDPI`
|
||||||
|
* `max-packets-per-flow-to-analyze` (N, safe): max. packets to analyze before sending an `analyse` event, requires `-A`
|
||||||
|
* `error-event-threshold-n` (N, safe): max. error events to send until threshold time has passed
|
||||||
|
* `error-event-threshold-time` (N, safe): time after which the error event threshold resets
|
||||||
|
|
||||||
# test
|
# test
|
||||||
|
|
||||||
The recommended way to run integration / diff tests:
|
The recommended way to run regression / diff tests:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
mkdir build
|
cmake -S . -B ./build-like-ci \
|
||||||
cd build
|
-DBUILD_NDPI=ON -DENABLE_ZLIB=ON -DBUILD_EXAMPLES=ON
|
||||||
cmake .. -DBUILD_NDPI=ON
|
# optional: -DENABLE_CURL=ON -DENABLE_SANITIZER=ON
|
||||||
make nDPId-test test
|
./test/run_tests.sh ./libnDPI ./build-like-ci/nDPId-test
|
||||||
|
# or: make -C ./build-like-ci test
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively you can run some integration tests manually:
|
Run `./test/run_tests.sh` to see some usage information.
|
||||||
|
|
||||||
`./test/run_tests.sh [/path/to/libnDPI/root/directory] [/path/to/nDPId-test]`
|
|
||||||
|
|
||||||
e.g.:
|
|
||||||
|
|
||||||
`./test/run_tests.sh [${HOME}/git/nDPI] [${HOME}/git/nDPId/build/nDPId-test]`
|
|
||||||
|
|
||||||
Remember that all test results are tied to a specific libnDPI commit hash
|
Remember that all test results are tied to a specific libnDPI commit hash
|
||||||
as part of the `git submodule`. Using `test/run_tests.s` for other commit hashes
|
as part of the `git submodule`. Using `test/run_tests.sh` for other commit hashes
|
||||||
will most likely result in PCAP diff's.
|
will most likely result in PCAP diffs.
|
||||||
|
|
||||||
|
# Code Coverage
|
||||||
|
|
||||||
|
You may generate code coverage by using:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cmake -S . -B ./build-coverage \
|
||||||
|
-DENABLE_COVERAGE=ON -DENABLE_ZLIB=ON
|
||||||
|
# optional: -DBUILD_NDPI=ON
|
||||||
|
make -C ./build-coverage coverage-clean
|
||||||
|
make -C ./build-coverage clean
|
||||||
|
make -C ./build-coverage all
|
||||||
|
./test/run_tests.sh ./libnDPI ./build-coverage/nDPId-test
|
||||||
|
make -C ./build-coverage coverage
|
||||||
|
make -C ./build-coverage coverage-view
|
||||||
|
```
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
|
||||||
|
Special thanks to Damiano Verzulli ([@verzulli](https://github.com/verzulli)) from [GARRLab](https://www.garrlab.it) for providing server and test infrastructure.
|
||||||
|
|||||||
18
SECURITY.md
Normal file
18
SECURITY.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
I encourage you to submit a pull request if you have a solution or fix for anything even security vulnerabilities.
|
||||||
|
Your contributions help advance and enhance safety for all users :star:.
|
||||||
|
|
||||||
|
## Reporting a Bug :bug: :bug:
|
||||||
|
|
||||||
|
Simply use GitHub issues to report a bug with related information to debug the issue :pencil:.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability :closed_lock_with_key: :eyes:
|
||||||
|
|
||||||
|
For sensitive security issues, please email <toni@impl.cc> including the following information:
|
||||||
|
|
||||||
|
- Description of the vulnerability
|
||||||
|
- Steps to reproduce the issue
|
||||||
|
- Affected versions i.e. release tags, git commit hashes or git branch
|
||||||
|
- If applicable, a data sample (preferably `pcap/pcapng`) to reproduce
|
||||||
|
- If known, any mitigations or fixes for the issue
|
||||||
23
TODO.md
23
TODO.md
@@ -1,7 +1,20 @@
|
|||||||
# TODOs
|
# TODOs
|
||||||
|
|
||||||
1. unify `struct io_buffer` from nDPIsrvd.c and `struct nDPIsrvd_buffer` from nDPIsrvd.h
|
1.8:
|
||||||
2. improve nDPIsrvd buffer bloat handling (Do not fall back to blocking mode!)
|
|
||||||
3. improve UDP/TCP timeout handling by reading netfilter conntrack timeouts from /proc
|
* let nDPIsrvd (collector) connect to other nDPIsrvd instances (as distributor)
|
||||||
4. detect interface / timeout changes and apply them to nDPId
|
* nDPIsrvd GnuTLS support for TCP/IP distributor connections
|
||||||
5. implement AEAD crypto via libsodium (at least for TCP communication)
|
* provide nDPId-exportd daemon which will only send captured packets to an nDPId instance running on a different machine
|
||||||
|
|
||||||
|
2.0.0:
|
||||||
|
|
||||||
|
* switch to semantic versioning for the greater good ;)
|
||||||
|
|
||||||
|
no release plan:
|
||||||
|
|
||||||
|
* merge flow end/idle event into idle event (end is not really useful..)
|
||||||
|
* provide a shared library for C / C++ for distributor application developers
|
||||||
|
* improve UDP/TCP timeout handling by reading netfilter conntrack timeouts from /proc (or just read conntrack table entries)
|
||||||
|
* detect interface / timeout changes and apply them to nDPId
|
||||||
|
* switch to MIT or BSD License
|
||||||
|
* libdaq integration
|
||||||
|
|||||||
28
cmake/CheckEpoll.cmake
Normal file
28
cmake/CheckEpoll.cmake
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# - Check if the system supports epoll.
|
||||||
|
# CHECK_EPOLL(<var>)
|
||||||
|
# <var> - variable to store the result
|
||||||
|
# (1 for success, empty for failure)
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# This software is in the public domain, furnished "as is", without technical
|
||||||
|
# support, and with no warranty, express or implied, as to its usefulness for
|
||||||
|
# any purpose.
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
macro(CHECK_EPOLL VARIABLE)
|
||||||
|
if(UNIX)
|
||||||
|
if("${VARIABLE}" MATCHES "^${VARIABLE}$")
|
||||||
|
message(STATUS "Check if the system supports epoll")
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
check_symbol_exists(epoll_create "sys/epoll.h" EPOLL_PROTOTYPE_EXISTS)
|
||||||
|
|
||||||
|
if(EPOLL_PROTOTYPE_EXISTS)
|
||||||
|
message(STATUS "Check if the system supports epoll - yes")
|
||||||
|
set(${VARIABLE} 1 CACHE INTERNAL "Result of CHECK_EPOLL" FORCE)
|
||||||
|
else(EPOLL_PROTOTYPE_EXISTS)
|
||||||
|
message(STATUS "Check if the system supports epoll - no")
|
||||||
|
set(${VARIABLE} "" CACHE INTERNAL "Result of CHECK_EPOLL" FORCE)
|
||||||
|
endif(EPOLL_PROTOTYPE_EXISTS)
|
||||||
|
endif("${VARIABLE}" MATCHES "^${VARIABLE}$")
|
||||||
|
endif(UNIX)
|
||||||
|
endmacro(CHECK_EPOLL)
|
||||||
36
config.h
36
config.h
@@ -2,6 +2,7 @@
|
|||||||
#define CONFIG_H 1
|
#define CONFIG_H 1
|
||||||
|
|
||||||
/* macros shared across multiple executables */
|
/* macros shared across multiple executables */
|
||||||
|
#define DEFAULT_CHUSER "nobody"
|
||||||
#define COLLECTOR_UNIX_SOCKET "/tmp/ndpid-collector.sock"
|
#define COLLECTOR_UNIX_SOCKET "/tmp/ndpid-collector.sock"
|
||||||
#define DISTRIBUTOR_UNIX_SOCKET "/tmp/ndpid-distributor.sock"
|
#define DISTRIBUTOR_UNIX_SOCKET "/tmp/ndpid-distributor.sock"
|
||||||
#define DISTRIBUTOR_HOST "127.0.0.1"
|
#define DISTRIBUTOR_HOST "127.0.0.1"
|
||||||
@@ -11,25 +12,44 @@
|
|||||||
* NOTE: Buffer size needs to keep in sync with other implementations
|
* NOTE: Buffer size needs to keep in sync with other implementations
|
||||||
* e.g. dependencies/nDPIsrvd.py
|
* e.g. dependencies/nDPIsrvd.py
|
||||||
*/
|
*/
|
||||||
#define NETWORK_BUFFER_MAX_SIZE 12288u /* 8192 + 4096 */
|
#define NETWORK_BUFFER_MAX_SIZE 33792u /* 8192 + 8192 + 8192 + 8192 + 1024 */
|
||||||
#define NETWORK_BUFFER_LENGTH_DIGITS 5u
|
#define NETWORK_BUFFER_LENGTH_DIGITS 5u
|
||||||
#define NETWORK_BUFFER_LENGTH_DIGITS_STR "5"
|
#define NETWORK_BUFFER_LENGTH_DIGITS_STR "5"
|
||||||
|
|
||||||
|
#define PFRING_BUFFER_SIZE 65536u
|
||||||
|
|
||||||
|
#define TIME_S_TO_US(s) (s * 1000llu * 1000llu)
|
||||||
|
|
||||||
/* nDPId default config options */
|
/* nDPId default config options */
|
||||||
#define nDPId_PIDFILE "/tmp/ndpid.pid"
|
#define nDPId_PIDFILE "/tmp/ndpid.pid"
|
||||||
#define nDPId_MAX_FLOWS_PER_THREAD 4096u
|
#define nDPId_MAX_FLOWS_PER_THREAD 65536u
|
||||||
#define nDPId_MAX_IDLE_FLOWS_PER_THREAD 512u
|
#define nDPId_MAX_IDLE_FLOWS_PER_THREAD (nDPId_MAX_FLOWS_PER_THREAD / 32u)
|
||||||
#define nDPId_TICK_RESOLUTION 1000u
|
|
||||||
#define nDPId_MAX_READER_THREADS 32u
|
#define nDPId_MAX_READER_THREADS 32u
|
||||||
#define nDPId_IDLE_SCAN_PERIOD 10000u /* 10 sec */
|
#define nDPId_ERROR_EVENT_THRESHOLD_N 16u
|
||||||
#define nDPId_IDLE_TIME 600000u /* 600 sec */
|
#define nDPId_ERROR_EVENT_THRESHOLD_TIME TIME_S_TO_US(10u) /* 10 sec */
|
||||||
#define nDPId_TCP_POST_END_FLOW_TIME 60000u /* 60 sec */
|
#define nDPId_DAEMON_STATUS_INTERVAL TIME_S_TO_US(600u) /* 600 sec */
|
||||||
|
#define nDPId_MEMORY_PROFILING_LOG_INTERVAL TIME_S_TO_US(5u) /* 5 sec */
|
||||||
|
#define nDPId_COMPRESSION_SCAN_INTERVAL TIME_S_TO_US(20u) /* 20 sec */
|
||||||
|
#define nDPId_COMPRESSION_FLOW_INACTIVITY TIME_S_TO_US(30u) /* 30 sec */
|
||||||
|
#define nDPId_FLOW_SCAN_INTERVAL TIME_S_TO_US(10u) /* 10 sec */
|
||||||
|
#define nDPId_GENERIC_IDLE_TIME TIME_S_TO_US(600u) /* 600 sec */
|
||||||
|
#define nDPId_ICMP_IDLE_TIME TIME_S_TO_US(120u) /* 120 sec */
|
||||||
|
#define nDPId_TCP_IDLE_TIME TIME_S_TO_US(7440u) /* 7440 sec */
|
||||||
|
#define nDPId_UDP_IDLE_TIME TIME_S_TO_US(180u) /* 180 sec */
|
||||||
|
#define nDPId_TCP_POST_END_FLOW_TIME TIME_S_TO_US(120u) /* 120 sec */
|
||||||
#define nDPId_THREAD_DISTRIBUTION_SEED 0x03dd018b
|
#define nDPId_THREAD_DISTRIBUTION_SEED 0x03dd018b
|
||||||
|
#define nDPId_PACKETS_PLEN_MAX 8192u /* 8kB */
|
||||||
#define nDPId_PACKETS_PER_FLOW_TO_SEND 15u
|
#define nDPId_PACKETS_PER_FLOW_TO_SEND 15u
|
||||||
#define nDPId_PACKETS_PER_FLOW_TO_PROCESS 255u
|
#define nDPId_PACKETS_PER_FLOW_TO_PROCESS 32u
|
||||||
|
#define nDPId_PACKETS_PER_FLOW_TO_ANALYZE 32u
|
||||||
|
#define nDPId_ANALYZE_PLEN_MAX 1504u
|
||||||
|
#define nDPId_ANALYZE_PLEN_BIN_LEN 32u
|
||||||
|
#define nDPId_ANALYZE_PLEN_NUM_BINS 48u
|
||||||
#define nDPId_FLOW_STRUCT_SEED 0x5defc104
|
#define nDPId_FLOW_STRUCT_SEED 0x5defc104
|
||||||
|
|
||||||
/* nDPIsrvd default config options */
|
/* nDPIsrvd default config options */
|
||||||
#define nDPIsrvd_PIDFILE "/tmp/ndpisrvd.pid"
|
#define nDPIsrvd_PIDFILE "/tmp/ndpisrvd.pid"
|
||||||
|
#define nDPIsrvd_MAX_REMOTE_DESCRIPTORS 128
|
||||||
|
#define nDPIsrvd_MAX_WRITE_BUFFERS 1024
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
10
dependencies/jsmn/README.md
vendored
10
dependencies/jsmn/README.md
vendored
@@ -89,7 +89,7 @@ jsmn_parser p;
|
|||||||
jsmntok_t t[128]; /* We expect no more than 128 JSON tokens */
|
jsmntok_t t[128]; /* We expect no more than 128 JSON tokens */
|
||||||
|
|
||||||
jsmn_init(&p);
|
jsmn_init(&p);
|
||||||
r = jsmn_parse(&p, s, strlen(s), t, 128);
|
r = jsmn_parse(&p, s, strlen(s), t, 128); // "s" is the char array holding the json content
|
||||||
```
|
```
|
||||||
|
|
||||||
Since jsmn is a single-header, header-only library, for more complex use cases
|
Since jsmn is a single-header, header-only library, for more complex use cases
|
||||||
@@ -113,10 +113,10 @@ Token types are described by `jsmntype_t`:
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
JSMN_UNDEFINED = 0,
|
JSMN_UNDEFINED = 0,
|
||||||
JSMN_OBJECT = 1,
|
JSMN_OBJECT = 1 << 0,
|
||||||
JSMN_ARRAY = 2,
|
JSMN_ARRAY = 1 << 1,
|
||||||
JSMN_STRING = 3,
|
JSMN_STRING = 1 << 2,
|
||||||
JSMN_PRIMITIVE = 4
|
JSMN_PRIMITIVE = 1 << 3
|
||||||
} jsmntype_t;
|
} jsmntype_t;
|
||||||
|
|
||||||
**Note:** Unlike JSON data types, primitive tokens are not divided into
|
**Note:** Unlike JSON data types, primitive tokens are not divided into
|
||||||
|
|||||||
14
dependencies/jsmn/jsmn.h
vendored
14
dependencies/jsmn/jsmn.h
vendored
@@ -45,10 +45,10 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
JSMN_UNDEFINED = 0,
|
JSMN_UNDEFINED = 0,
|
||||||
JSMN_OBJECT = 1,
|
JSMN_OBJECT = 1 << 0,
|
||||||
JSMN_ARRAY = 2,
|
JSMN_ARRAY = 1 << 1,
|
||||||
JSMN_STRING = 3,
|
JSMN_STRING = 1 << 2,
|
||||||
JSMN_PRIMITIVE = 4
|
JSMN_PRIMITIVE = 1 << 3
|
||||||
} jsmntype_t;
|
} jsmntype_t;
|
||||||
|
|
||||||
enum jsmnerr {
|
enum jsmnerr {
|
||||||
@@ -196,10 +196,10 @@ static int jsmn_parse_string(jsmn_parser *parser, const char *js,
|
|||||||
jsmntok_t *token;
|
jsmntok_t *token;
|
||||||
|
|
||||||
int start = parser->pos;
|
int start = parser->pos;
|
||||||
|
|
||||||
parser->pos++;
|
|
||||||
|
|
||||||
/* Skip starting quote */
|
/* Skip starting quote */
|
||||||
|
parser->pos++;
|
||||||
|
|
||||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||||
char c = js[parser->pos];
|
char c = js[parser->pos];
|
||||||
|
|
||||||
|
|||||||
1443
dependencies/nDPIsrvd.h
vendored
1443
dependencies/nDPIsrvd.h
vendored
File diff suppressed because it is too large
Load Diff
539
dependencies/nDPIsrvd.py
vendored
539
dependencies/nDPIsrvd.py
vendored
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import array
|
import array
|
||||||
import base64
|
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
@@ -17,29 +16,25 @@ except ImportError:
|
|||||||
sys.stderr.write('Python module colorama not found, using fallback.\n')
|
sys.stderr.write('Python module colorama not found, using fallback.\n')
|
||||||
USE_COLORAMA=False
|
USE_COLORAMA=False
|
||||||
|
|
||||||
try:
|
|
||||||
import scapy.all
|
|
||||||
except ImportError:
|
|
||||||
sys.stderr.write('Python module scapy not found, PCAP generation will fail!\n')
|
|
||||||
|
|
||||||
DEFAULT_HOST = '127.0.0.1'
|
DEFAULT_HOST = '127.0.0.1'
|
||||||
DEFAULT_PORT = 7000
|
DEFAULT_PORT = 7000
|
||||||
DEFAULT_UNIX = '/tmp/ndpid-distributor.sock'
|
DEFAULT_UNIX = '/tmp/ndpid-distributor.sock'
|
||||||
|
|
||||||
NETWORK_BUFFER_MIN_SIZE = 6 # NETWORK_BUFFER_LENGTH_DIGITS + 1
|
NETWORK_BUFFER_MIN_SIZE = 6 # NETWORK_BUFFER_LENGTH_DIGITS + 1
|
||||||
NETWORK_BUFFER_MAX_SIZE = 12288 # Please keep this value in sync with the one in config.h
|
NETWORK_BUFFER_MAX_SIZE = 33792 # Please keep this value in sync with the one in config.h
|
||||||
|
nDPId_PACKETS_PLEN_MAX = 8192 # Please keep this value in sync with the one in config.h
|
||||||
|
|
||||||
PKT_TYPE_ETH_IP4 = 0x0800
|
PKT_TYPE_ETH_IP4 = 0x0800
|
||||||
PKT_TYPE_ETH_IP6 = 0x86DD
|
PKT_TYPE_ETH_IP6 = 0x86DD
|
||||||
|
|
||||||
|
|
||||||
class TermColor:
|
class TermColor:
|
||||||
HINT = '\033[33m'
|
HINT = '\033[33m'
|
||||||
WARNING = '\033[93m'
|
WARNING = '\033[93m'
|
||||||
FAIL = '\033[91m'
|
FAIL = '\033[91m'
|
||||||
BOLD = '\033[1m'
|
BOLD = '\033[1m'
|
||||||
END = '\033[0m'
|
END = '\033[0m'
|
||||||
BLINK = '\x1b[5m'
|
BLINK = '\x1b[5m'
|
||||||
|
|
||||||
if USE_COLORAMA is True:
|
if USE_COLORAMA is True:
|
||||||
COLOR_TUPLES = [ (Fore.BLUE, [Back.RED, Back.MAGENTA, Back.WHITE]),
|
COLOR_TUPLES = [ (Fore.BLUE, [Back.RED, Back.MAGENTA, Back.WHITE]),
|
||||||
@@ -57,6 +52,21 @@ class TermColor:
|
|||||||
(Fore.LIGHTWHITE_EX, [Back.LIGHTBLACK_EX, Back.BLACK]),
|
(Fore.LIGHTWHITE_EX, [Back.LIGHTBLACK_EX, Back.BLACK]),
|
||||||
(Fore.LIGHTYELLOW_EX, [Back.LIGHTRED_EX, Back.RED]) ]
|
(Fore.LIGHTYELLOW_EX, [Back.LIGHTRED_EX, Back.RED]) ]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def disableColor():
|
||||||
|
TermColor.HINT = ''
|
||||||
|
TermColor.WARNING = ''
|
||||||
|
TermColor.FAIL = ''
|
||||||
|
TermColor.BOLD = ''
|
||||||
|
TermColor.END = ''
|
||||||
|
TermColor.BLINK = ''
|
||||||
|
global USE_COLORAMA
|
||||||
|
USE_COLORAMA = False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def disableBlink():
|
||||||
|
TermColor.BLINK = ''
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def calcColorHash(string):
|
def calcColorHash(string):
|
||||||
h = 0
|
h = 0
|
||||||
@@ -74,44 +84,212 @@ class TermColor:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def setColorByString(string):
|
def setColorByString(string):
|
||||||
|
global USE_COLORAMA
|
||||||
if USE_COLORAMA is True:
|
if USE_COLORAMA is True:
|
||||||
fg_color, bg_color = TermColor.getColorsByHash(string)
|
fg_color, bg_color = TermColor.getColorsByHash(string)
|
||||||
color_hash = TermColor.calcColorHash(string)
|
|
||||||
return '{}{}{}{}{}'.format(Style.BRIGHT, fg_color, bg_color, string, Style.RESET_ALL)
|
return '{}{}{}{}{}'.format(Style.BRIGHT, fg_color, bg_color, string, Style.RESET_ALL)
|
||||||
else:
|
else:
|
||||||
return '{}{}{}'.format(TermColor.BOLD, string, TermColor.END)
|
return '{}{}{}'.format(TermColor.BOLD, string, TermColor.END)
|
||||||
|
|
||||||
|
class ThreadData:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Instance:
|
||||||
|
|
||||||
|
def __init__(self, alias, source):
|
||||||
|
self.alias = str(alias)
|
||||||
|
self.source = str(source)
|
||||||
|
self.flows = dict()
|
||||||
|
self.thread_data = dict()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '<%s.%s object at %s with alias %s, source %s>' % (
|
||||||
|
self.__class__.__module__,
|
||||||
|
self.__class__.__name__,
|
||||||
|
hex(id(self)),
|
||||||
|
self.alias,
|
||||||
|
self.source
|
||||||
|
)
|
||||||
|
|
||||||
|
def getThreadData(self, thread_id):
|
||||||
|
if thread_id not in self.thread_data:
|
||||||
|
return None
|
||||||
|
return self.thread_data[thread_id]
|
||||||
|
|
||||||
|
def getThreadDataFromJSON(self, json_dict):
|
||||||
|
if 'thread_id' not in json_dict:
|
||||||
|
return None
|
||||||
|
return self.getThreadData(json_dict['thread_id'])
|
||||||
|
|
||||||
|
def getMostRecentFlowTime(self, thread_id):
|
||||||
|
return self.thread_data[thread_id].most_recent_flow_time
|
||||||
|
|
||||||
|
def setMostRecentFlowTime(self, thread_id, most_recent_flow_time):
|
||||||
|
if thread_id in self.thread_data:
|
||||||
|
return self.thread_data[thread_id]
|
||||||
|
|
||||||
|
self.thread_data[thread_id] = ThreadData()
|
||||||
|
self.thread_data[thread_id].most_recent_flow_time = most_recent_flow_time
|
||||||
|
return self.thread_data[thread_id]
|
||||||
|
|
||||||
|
def getMostRecentFlowTimeFromJSON(self, json_dict):
|
||||||
|
if 'thread_id' not in json_dict:
|
||||||
|
return 0
|
||||||
|
return self.getThreadData(json_dict['thread_id']).most_recent_flow_time
|
||||||
|
|
||||||
|
def setMostRecentFlowTimeFromJSON(self, json_dict):
|
||||||
|
if 'thread_id' not in json_dict:
|
||||||
|
return
|
||||||
|
thread_id = json_dict['thread_id']
|
||||||
|
if 'thread_ts_usec' in json_dict:
|
||||||
|
mrtf = self.getMostRecentFlowTime(thread_id) if thread_id in self.thread_data else 0
|
||||||
|
self.setMostRecentFlowTime(thread_id, max(json_dict['thread_ts_usec'], mrtf))
|
||||||
|
|
||||||
class Flow:
|
class Flow:
|
||||||
flow_id = -1
|
|
||||||
|
def __init__(self, flow_id, thread_id):
|
||||||
|
self.flow_id = flow_id
|
||||||
|
self.thread_id = thread_id
|
||||||
|
self.flow_last_seen = -1
|
||||||
|
self.flow_idle_time = -1
|
||||||
|
self.cleanup_reason = -1
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '<%s.%s object at %s with flow id %d>' % (
|
||||||
|
self.__class__.__module__,
|
||||||
|
self.__class__.__name__,
|
||||||
|
hex(id(self)),
|
||||||
|
self.flow_id
|
||||||
|
)
|
||||||
|
|
||||||
class FlowManager:
|
class FlowManager:
|
||||||
def __init__(self):
|
CLEANUP_REASON_INVALID = 0
|
||||||
self.__flows = dict()
|
CLEANUP_REASON_DAEMON_INIT = 1 # can happen if kill -SIGKILL $(pidof nDPId) or restart after SIGSEGV
|
||||||
|
CLEANUP_REASON_DAEMON_SHUTDOWN = 2 # graceful shutdown e.g. kill -SIGTERM $(pidof nDPId)
|
||||||
|
CLEANUP_REASON_FLOW_END = 3
|
||||||
|
CLEANUP_REASON_FLOW_IDLE = 4
|
||||||
|
CLEANUP_REASON_FLOW_TIMEOUT = 5 # nDPId died a long time ago w/o restart?
|
||||||
|
CLEANUP_REASON_APP_SHUTDOWN = 6 # your python app called FlowManager.doShutdown()
|
||||||
|
|
||||||
def __buildFlowKey(self, json_dict):
|
def __init__(self):
|
||||||
if 'flow_id' not in json_dict or \
|
self.instances = dict()
|
||||||
'alias' not in json_dict or \
|
|
||||||
|
def getInstance(self, json_dict):
|
||||||
|
if 'alias' not in json_dict or \
|
||||||
'source' not in json_dict:
|
'source' not in json_dict:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return str(json_dict['alias']) + str(json_dict['source']) + str(json_dict['flow_id'])
|
alias = json_dict['alias']
|
||||||
|
source = json_dict['source']
|
||||||
|
|
||||||
def getFlow(self, json_dict):
|
if alias not in self.instances:
|
||||||
event = json_dict['flow_event_name'].lower() if 'flow_event_name' in json_dict else ''
|
self.instances[alias] = dict()
|
||||||
flow_key = self.__buildFlowKey(json_dict)
|
if source not in self.instances[alias]:
|
||||||
flow = None
|
self.instances[alias][source] = Instance(alias, source)
|
||||||
|
|
||||||
if flow_key is None:
|
self.instances[alias][source].setMostRecentFlowTimeFromJSON(json_dict)
|
||||||
|
|
||||||
|
return self.instances[alias][source]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getLastPacketTime(instance, flow_id, json_dict):
|
||||||
|
return max(int(json_dict['flow_src_last_pkt_time']), int(json_dict['flow_dst_last_pkt_time']), instance.flows[flow_id].flow_last_seen)
|
||||||
|
|
||||||
|
def getFlow(self, instance, json_dict):
|
||||||
|
if 'flow_id' not in json_dict:
|
||||||
return None
|
return None
|
||||||
if flow_key not in self.__flows:
|
|
||||||
self.__flows[flow_key] = Flow()
|
|
||||||
self.__flows[flow_key].flow_id = int(json_dict['flow_id'])
|
|
||||||
flow = self.__flows[flow_key]
|
|
||||||
if event == 'end' or event == 'idle':
|
|
||||||
flow = self.__flows[flow_key]
|
|
||||||
del self.__flows[flow_key]
|
|
||||||
|
|
||||||
return flow
|
flow_id = int(json_dict['flow_id'])
|
||||||
|
|
||||||
|
if flow_id in instance.flows:
|
||||||
|
instance.flows[flow_id].flow_last_seen = FlowManager.getLastPacketTime(instance, flow_id, json_dict)
|
||||||
|
instance.flows[flow_id].flow_idle_time = int(json_dict['flow_idle_time'])
|
||||||
|
return instance.flows[flow_id]
|
||||||
|
|
||||||
|
thread_id = int(json_dict['thread_id'])
|
||||||
|
instance.flows[flow_id] = Flow(flow_id, thread_id)
|
||||||
|
instance.flows[flow_id].flow_last_seen = FlowManager.getLastPacketTime(instance, flow_id, json_dict)
|
||||||
|
instance.flows[flow_id].flow_idle_time = int(json_dict['flow_idle_time'])
|
||||||
|
instance.flows[flow_id].cleanup_reason = FlowManager.CLEANUP_REASON_INVALID
|
||||||
|
|
||||||
|
return instance.flows[flow_id]
|
||||||
|
|
||||||
|
def getFlowsToCleanup(self, instance, json_dict):
|
||||||
|
flows = dict()
|
||||||
|
|
||||||
|
if 'daemon_event_name' in json_dict:
|
||||||
|
if json_dict['daemon_event_name'].lower() == 'init' or \
|
||||||
|
json_dict['daemon_event_name'].lower() == 'shutdown':
|
||||||
|
# invalidate all existing flows with that alias/source/thread_id
|
||||||
|
for flow_id in instance.flows:
|
||||||
|
flow = instance.flows[flow_id]
|
||||||
|
if flow.thread_id != int(json_dict['thread_id']):
|
||||||
|
continue
|
||||||
|
if json_dict['daemon_event_name'].lower() == 'init':
|
||||||
|
flow.cleanup_reason = FlowManager.CLEANUP_REASON_DAEMON_INIT
|
||||||
|
else:
|
||||||
|
flow.cleanup_reason = FlowManager.CLEANUP_REASON_DAEMON_SHUTDOWN
|
||||||
|
flows[flow_id] = flow
|
||||||
|
for flow_id in flows:
|
||||||
|
del instance.flows[flow_id]
|
||||||
|
if len(instance.flows) == 0:
|
||||||
|
del self.instances[instance.alias][instance.source]
|
||||||
|
|
||||||
|
elif 'flow_event_name' in json_dict and \
|
||||||
|
(json_dict['flow_event_name'].lower() == 'end' or \
|
||||||
|
json_dict['flow_event_name'].lower() == 'idle' or \
|
||||||
|
json_dict['flow_event_name'].lower() == 'guessed' or \
|
||||||
|
json_dict['flow_event_name'].lower() == 'not-detected' or \
|
||||||
|
json_dict['flow_event_name'].lower() == 'detected'):
|
||||||
|
flow_id = json_dict['flow_id']
|
||||||
|
if json_dict['flow_event_name'].lower() == 'end':
|
||||||
|
instance.flows[flow_id].cleanup_reason = FlowManager.CLEANUP_REASON_FLOW_END
|
||||||
|
elif json_dict['flow_event_name'].lower() == 'idle':
|
||||||
|
instance.flows[flow_id].cleanup_reason = FlowManager.CLEANUP_REASON_FLOW_IDLE
|
||||||
|
# TODO: Flow Guessing/Detection can happen right before an idle event.
|
||||||
|
# We need to prevent that it results in a CLEANUP_REASON_FLOW_TIMEOUT.
|
||||||
|
# This may cause inconsistency and needs to be handled in another way.
|
||||||
|
if json_dict['flow_event_name'].lower() != 'guessed' and \
|
||||||
|
json_dict['flow_event_name'].lower() != 'not-detected' and \
|
||||||
|
json_dict['flow_event_name'].lower() != 'detected':
|
||||||
|
flows[flow_id] = instance.flows.pop(flow_id)
|
||||||
|
|
||||||
|
elif 'flow_last_seen' in json_dict:
|
||||||
|
if int(json_dict['flow_last_seen']) + int(json_dict['flow_idle_time']) < \
|
||||||
|
instance.getMostRecentFlowTimeFromJSON(json_dict):
|
||||||
|
flow_id = json_dict['flow_id']
|
||||||
|
instance.flows[flow_id].cleanup_reason = FlowManager.CLEANUP_REASON_FLOW_TIMEOUT
|
||||||
|
flows[flow_id] = instance.flows.pop(flow_id)
|
||||||
|
|
||||||
|
return flows
|
||||||
|
|
||||||
|
def doShutdown(self):
|
||||||
|
flows = dict()
|
||||||
|
|
||||||
|
for alias in self.instances:
|
||||||
|
for source in self.instances[alias]:
|
||||||
|
for flow_id in self.instances[alias][source].flows:
|
||||||
|
flow = self.instances[alias][source].flows[flow_id]
|
||||||
|
flow.cleanup_reason = FlowManager.CLEANUP_REASON_APP_SHUTDOWN
|
||||||
|
flows[flow_id] = flow
|
||||||
|
|
||||||
|
del self.instances
|
||||||
|
|
||||||
|
return flows
|
||||||
|
|
||||||
|
def verifyFlows(self):
|
||||||
|
invalid_flows = list()
|
||||||
|
|
||||||
|
for alias in self.instances:
|
||||||
|
for source in self.instances[alias]:
|
||||||
|
for flow_id in self.instances[alias][source].flows:
|
||||||
|
thread_id = self.instances[alias][source].flows[flow_id].thread_id
|
||||||
|
if self.instances[alias][source].flows[flow_id].flow_last_seen + \
|
||||||
|
self.instances[alias][source].flows[flow_id].flow_idle_time < \
|
||||||
|
self.instances[alias][source].getMostRecentFlowTime(thread_id):
|
||||||
|
invalid_flows += [flow_id]
|
||||||
|
|
||||||
|
return invalid_flows
|
||||||
|
|
||||||
class nDPIsrvdException(Exception):
|
class nDPIsrvdException(Exception):
|
||||||
UNSUPPORTED_ADDRESS_TYPE = 1
|
UNSUPPORTED_ADDRESS_TYPE = 1
|
||||||
@@ -119,6 +297,8 @@ class nDPIsrvdException(Exception):
|
|||||||
SOCKET_CONNECTION_BROKEN = 3
|
SOCKET_CONNECTION_BROKEN = 3
|
||||||
INVALID_LINE_RECEIVED = 4
|
INVALID_LINE_RECEIVED = 4
|
||||||
CALLBACK_RETURNED_FALSE = 5
|
CALLBACK_RETURNED_FALSE = 5
|
||||||
|
SOCKET_TIMEOUT = 6
|
||||||
|
JSON_DECODE_ERROR = 7
|
||||||
|
|
||||||
def __init__(self, etype):
|
def __init__(self, etype):
|
||||||
self.etype = etype
|
self.etype = etype
|
||||||
@@ -159,10 +339,57 @@ class CallbackReturnedFalse(nDPIsrvdException):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return 'Callback returned False, abort.'
|
return 'Callback returned False, abort.'
|
||||||
|
|
||||||
|
class SocketTimeout(nDPIsrvdException):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(nDPIsrvdException.SOCKET_TIMEOUT)
|
||||||
|
def __str__(self):
|
||||||
|
return 'Socket timeout.'
|
||||||
|
|
||||||
|
class JsonDecodeError(nDPIsrvdException):
|
||||||
|
def __init__(self, json_exception, failed_line):
|
||||||
|
super().__init__(nDPIsrvdException.JSON_DECODE_ERROR)
|
||||||
|
self.json_exception = json_exception
|
||||||
|
self.failed_line = failed_line
|
||||||
|
def __str__(self):
|
||||||
|
return '{}: {}'.format(self.json_exception, self.failed_line)
|
||||||
|
|
||||||
|
class JsonFilter():
|
||||||
|
def __init__(self, filter_string):
|
||||||
|
self.filter_string = filter_string
|
||||||
|
self.filter = compile(filter_string, '<string>', 'eval')
|
||||||
|
def evaluate(self, json_dict):
|
||||||
|
if type(json_dict) is not dict:
|
||||||
|
raise nDPIsrvdException('Could not evaluate JSON Filter: expected dictionary, got {}'.format(type(json_dict)))
|
||||||
|
return eval(self.filter, {'json_dict': json_dict})
|
||||||
|
|
||||||
class nDPIsrvdSocket:
|
class nDPIsrvdSocket:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.sock_family = None
|
self.sock_family = None
|
||||||
self.flow_mgr = FlowManager()
|
self.flow_mgr = FlowManager()
|
||||||
|
self.received_bytes = 0
|
||||||
|
self.json_filter = list()
|
||||||
|
|
||||||
|
def addFilter(self, filter_str):
|
||||||
|
self.json_filter.append(JsonFilter(filter_str))
|
||||||
|
|
||||||
|
def evalFilters(self, json_dict):
|
||||||
|
for jf in self.json_filter:
|
||||||
|
try:
|
||||||
|
json_filter_retval = jf.evaluate(json_dict)
|
||||||
|
except Exception as err:
|
||||||
|
print()
|
||||||
|
sys.stderr.write('Error while evaluating expression "{}"\n'.format(jf.filter_string))
|
||||||
|
raise err
|
||||||
|
|
||||||
|
if not isinstance(json_filter_retval, bool):
|
||||||
|
print()
|
||||||
|
sys.stderr.write('Error while evaluating expression "{}"\n'.format(jf.filter_string))
|
||||||
|
raise nDPIsrvdException('JSON Filter returned an invalid type: expected bool, got {}'.format(type(json_filter_retval)))
|
||||||
|
|
||||||
|
if json_filter_retval is False:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def connect(self, addr):
|
def connect(self, addr):
|
||||||
if type(addr) is tuple:
|
if type(addr) is tuple:
|
||||||
@@ -178,6 +405,11 @@ class nDPIsrvdSocket:
|
|||||||
self.msglen = 0
|
self.msglen = 0
|
||||||
self.digitlen = 0
|
self.digitlen = 0
|
||||||
self.lines = []
|
self.lines = []
|
||||||
|
self.failed_lines = []
|
||||||
|
self.filtered_lines = 0
|
||||||
|
|
||||||
|
def timeout(self, timeout):
|
||||||
|
self.sock.settimeout(timeout)
|
||||||
|
|
||||||
def receive(self):
|
def receive(self):
|
||||||
if len(self.buffer) == NETWORK_BUFFER_MAX_SIZE:
|
if len(self.buffer) == NETWORK_BUFFER_MAX_SIZE:
|
||||||
@@ -189,6 +421,11 @@ class nDPIsrvdSocket:
|
|||||||
except ConnectionResetError:
|
except ConnectionResetError:
|
||||||
connection_finished = True
|
connection_finished = True
|
||||||
recvd = bytes()
|
recvd = bytes()
|
||||||
|
except TimeoutError:
|
||||||
|
raise SocketTimeout()
|
||||||
|
except socket.timeout:
|
||||||
|
raise SocketTimeout()
|
||||||
|
|
||||||
if len(recvd) == 0:
|
if len(recvd) == 0:
|
||||||
connection_finished = True
|
connection_finished = True
|
||||||
|
|
||||||
@@ -212,6 +449,7 @@ class nDPIsrvdSocket:
|
|||||||
self.lines += [(recvd,self.msglen,self.digitlen)]
|
self.lines += [(recvd,self.msglen,self.digitlen)]
|
||||||
new_data_avail = True
|
new_data_avail = True
|
||||||
|
|
||||||
|
self.received_bytes += self.msglen + self.digitlen
|
||||||
self.msglen = 0
|
self.msglen = 0
|
||||||
self.digitlen = 0
|
self.digitlen = 0
|
||||||
|
|
||||||
@@ -220,21 +458,51 @@ class nDPIsrvdSocket:
|
|||||||
|
|
||||||
return new_data_avail
|
return new_data_avail
|
||||||
|
|
||||||
def parse(self, callback, global_user_data):
|
def parse(self, callback_json, callback_flow_cleanup, global_user_data):
|
||||||
retval = True
|
retval = True
|
||||||
index = 0
|
|
||||||
for received_json_line in self.lines:
|
|
||||||
json_dict = json.loads(received_json_line[0].decode('ascii', errors='replace'), strict=True)
|
|
||||||
if callback(json_dict, self.flow_mgr.getFlow(json_dict), global_user_data) is not True:
|
|
||||||
retval = False
|
|
||||||
break
|
|
||||||
index += 1
|
|
||||||
|
|
||||||
self.lines = self.lines[index:]
|
for received_line in self.lines:
|
||||||
|
try:
|
||||||
|
json_dict = json.loads(received_line[0].decode('ascii', errors='replace'), strict=True)
|
||||||
|
except json.decoder.JSONDecodeError as e:
|
||||||
|
json_dict = dict()
|
||||||
|
self.failed_lines += [received_line]
|
||||||
|
self.lines = self.lines[1:]
|
||||||
|
raise JsonDecodeError(e, received_line)
|
||||||
|
|
||||||
|
instance = self.flow_mgr.getInstance(json_dict)
|
||||||
|
if instance is None:
|
||||||
|
self.failed_lines += [received_line]
|
||||||
|
retval = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
current_flow = self.flow_mgr.getFlow(instance, json_dict)
|
||||||
|
filter_eval = self.evalFilters(json_dict)
|
||||||
|
if filter_eval is True:
|
||||||
|
try:
|
||||||
|
if callback_json(json_dict, instance, current_flow, global_user_data) is not True:
|
||||||
|
self.failed_lines += [received_line]
|
||||||
|
retval = False
|
||||||
|
except Exception as e:
|
||||||
|
self.failed_lines += [received_line]
|
||||||
|
self.lines = self.lines[1:]
|
||||||
|
raise(e)
|
||||||
|
else:
|
||||||
|
self.filtered_lines += 1
|
||||||
|
|
||||||
|
for _, flow in self.flow_mgr.getFlowsToCleanup(instance, json_dict).items():
|
||||||
|
if callback_flow_cleanup is None:
|
||||||
|
pass
|
||||||
|
elif filter_eval is True and callback_flow_cleanup(instance, flow, global_user_data) is not True:
|
||||||
|
self.failed_lines += [received_line]
|
||||||
|
self.lines = self.lines[1:]
|
||||||
|
retval = False
|
||||||
|
|
||||||
|
self.lines = self.lines[1:]
|
||||||
|
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
def loop(self, callback, global_user_data):
|
def loop(self, callback_json, callback_flow_cleanup, global_user_data):
|
||||||
throw_ex = None
|
throw_ex = None
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@@ -244,130 +512,41 @@ class nDPIsrvdSocket:
|
|||||||
except Exception as err:
|
except Exception as err:
|
||||||
throw_ex = err
|
throw_ex = err
|
||||||
|
|
||||||
if self.parse(callback, global_user_data) is False:
|
if self.parse(callback_json, callback_flow_cleanup, global_user_data) is False:
|
||||||
raise CallbackReturnedFalse()
|
raise CallbackReturnedFalse()
|
||||||
|
|
||||||
if throw_ex is not None:
|
if throw_ex is not None:
|
||||||
raise throw_ex
|
raise throw_ex
|
||||||
|
|
||||||
class PcapPacket:
|
def shutdown(self):
|
||||||
def __init__(self):
|
return self.flow_mgr.doShutdown().items()
|
||||||
self.pktdump = None
|
|
||||||
self.flow_id = 0
|
|
||||||
self.packets = []
|
|
||||||
self.__suffix = ''
|
|
||||||
self.__dump = False
|
|
||||||
self.__dumped = False
|
|
||||||
|
|
||||||
@staticmethod
|
def verify(self):
|
||||||
def isInitialized(current_flow):
|
if len(self.failed_lines) > 0:
|
||||||
return current_flow is not None and hasattr(current_flow, 'pcap_packet')
|
raise nDPIsrvdException('Failed lines > 0: {}'.format(len(self.failed_lines)))
|
||||||
|
return self.flow_mgr.verifyFlows()
|
||||||
|
|
||||||
@staticmethod
|
def defaultArgumentParser(desc='nDPIsrvd Python Interface', enable_json_filter=False,
|
||||||
def handleJSON(json_dict, current_flow):
|
help_formatter=argparse.ArgumentDefaultsHelpFormatter):
|
||||||
if 'flow_event_name' in json_dict:
|
parser = argparse.ArgumentParser(description=desc, formatter_class=help_formatter)
|
||||||
|
|
||||||
if json_dict['flow_event_name'] == 'new':
|
|
||||||
|
|
||||||
current_flow.pcap_packet = PcapPacket()
|
|
||||||
current_flow.pcap_packet.current_packet = 0
|
|
||||||
current_flow.pcap_packet.max_packets = json_dict['flow_max_packets']
|
|
||||||
current_flow.pcap_packet.flow_id = json_dict['flow_id']
|
|
||||||
|
|
||||||
elif PcapPacket.isInitialized(current_flow) is not True:
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
elif json_dict['flow_event_name'] == 'end' or json_dict['flow_event_name'] == 'idle':
|
|
||||||
|
|
||||||
try:
|
|
||||||
current_flow.pcap_packet.fin()
|
|
||||||
except RuntimeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
elif PcapPacket.isInitialized(current_flow) is True and \
|
|
||||||
('packet_event_name' in json_dict and json_dict['packet_event_name'] == 'packet-flow' and current_flow.pcap_packet.flow_id > 0) or \
|
|
||||||
('packet_event_name' in json_dict and json_dict['packet_event_name'] == 'packet' and 'pkt' in json_dict):
|
|
||||||
|
|
||||||
buffer_decoded = base64.b64decode(json_dict['pkt'], validate=True)
|
|
||||||
current_flow.pcap_packet.packets += [ ( buffer_decoded, json_dict['pkt_type'], json_dict['pkt_l3_offset'] ) ]
|
|
||||||
current_flow.pcap_packet.current_packet += 1
|
|
||||||
|
|
||||||
if current_flow.pcap_packet.current_packet != int(json_dict['flow_packet_id']):
|
|
||||||
raise RuntimeError('Packet IDs not in sync (local: {}, remote: {}).'.format(current_flow.pcap_packet.current_packet, int(json_dict['flow_packet_id'])))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def getIp(packet):
|
|
||||||
if packet[1] == PKT_TYPE_ETH_IP4:
|
|
||||||
return scapy.all.IP(packet[0][packet[2]:])
|
|
||||||
elif packet[1] == PKT_TYPE_ETH_IP6:
|
|
||||||
return scapy.all.IPv6(packet[0][packet[2]:])
|
|
||||||
else:
|
|
||||||
raise RuntimeError('packet type unknown: {}'.format(packet[1]))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def getTCPorUDP(packet):
|
|
||||||
p = PcapPacket.getIp(packet)
|
|
||||||
if p.haslayer(scapy.all.TCP):
|
|
||||||
return p.getlayer(scapy.all.TCP)
|
|
||||||
elif p.haslayer(scapy.all.UDP):
|
|
||||||
return p.getlayer(scapy.all.UDP)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def setSuffix(self, filename_suffix):
|
|
||||||
self.__suffix = filename_suffix
|
|
||||||
|
|
||||||
def doDump(self):
|
|
||||||
self.__dump = True
|
|
||||||
|
|
||||||
def fin(self):
|
|
||||||
if self.__dumped is True:
|
|
||||||
raise RuntimeError('Flow {} already dumped.'.format(self.flow_id))
|
|
||||||
if self.__dump is False:
|
|
||||||
raise RuntimeError('Flow {} should not be dumped.'.format(self.flow_id))
|
|
||||||
|
|
||||||
emptyTCPorUDPcount = 0;
|
|
||||||
for packet in self.packets:
|
|
||||||
p = PcapPacket.getTCPorUDP(packet)
|
|
||||||
if p is not None:
|
|
||||||
if p.haslayer(scapy.all.Padding) and len(p.payload) - len(p[scapy.all.Padding]) == 0:
|
|
||||||
emptyTCPorUDPcount += 1
|
|
||||||
elif len(p.payload) == 0:
|
|
||||||
emptyTCPorUDPcount += 1
|
|
||||||
|
|
||||||
if emptyTCPorUDPcount == len(self.packets):
|
|
||||||
raise RuntimeError('Flow {} does not contain any packets({}) with non-empty layer4 payload.'.format(self.flow_id, len(self.packets)))
|
|
||||||
|
|
||||||
if self.pktdump is None:
|
|
||||||
if self.flow_id == 0:
|
|
||||||
self.pktdump = scapy.all.PcapWriter('packet-{}.pcap'.format(self.__suffix),
|
|
||||||
append=True, sync=True)
|
|
||||||
else:
|
|
||||||
self.pktdump = scapy.all.PcapWriter('flow-{}-{}.pcap'.format(self.__suffix, self.flow_id),
|
|
||||||
append=False, sync=True)
|
|
||||||
|
|
||||||
for packet in self.packets:
|
|
||||||
self.pktdump.write(PcapPacket.getIp(packet))
|
|
||||||
|
|
||||||
self.pktdump.close()
|
|
||||||
self.__dumped = True
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def defaultArgumentParser():
|
|
||||||
parser = argparse.ArgumentParser(description='nDPIsrvd options', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
||||||
parser.add_argument('--host', type=str, help='nDPIsrvd host IP')
|
parser.add_argument('--host', type=str, help='nDPIsrvd host IP')
|
||||||
parser.add_argument('--port', type=int, default=DEFAULT_PORT, help='nDPIsrvd TCP port')
|
parser.add_argument('--port', type=int, default=DEFAULT_PORT, help='nDPIsrvd TCP port')
|
||||||
parser.add_argument('--unix', type=str, help='nDPIsrvd unix socket path')
|
parser.add_argument('--unix', type=str, help='nDPIsrvd unix socket path')
|
||||||
|
if enable_json_filter is True:
|
||||||
|
parser.add_argument('--filter', type=str, action='append',
|
||||||
|
help='Set a filter string which if evaluates to True will invoke the JSON callback.\n'
|
||||||
|
'Example: json_dict[\'flow_event_name\'] == \'detected\' will only process \'detected\' events.')
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
def toSeconds(usec):
|
||||||
|
return usec / (1000 * 1000)
|
||||||
|
|
||||||
def validateAddress(args):
|
def validateAddress(args):
|
||||||
tcp_addr_set = False
|
tcp_addr_set = False
|
||||||
address = None
|
address = None
|
||||||
|
|
||||||
if args.host is None:
|
if args.host is None:
|
||||||
address_tcpip = (DEFAULT_HOST, DEFAULT_PORT)
|
address_tcpip = (DEFAULT_HOST, args.port)
|
||||||
else:
|
else:
|
||||||
address_tcpip = (args.host, args.port)
|
address_tcpip = (args.host, args.port)
|
||||||
tcp_addr_set = True
|
tcp_addr_set = True
|
||||||
@@ -389,28 +568,68 @@ def validateAddress(args):
|
|||||||
|
|
||||||
return address
|
return address
|
||||||
|
|
||||||
global schema
|
def prepareJsonFilter(args, nsock):
|
||||||
schema = {'packet_event_schema' : None, 'basic_event_schema' : None, 'daemon_event_schema' : None, 'flow_event_schema' : None}
|
# HowTo use JSON Filters:
|
||||||
|
# Add `--filter [FILTER_STRING]` to the Python scripts that support JSON filtering.
|
||||||
|
# Examples:
|
||||||
|
# ./examples/py-json-stdout/json-stdout.py --filter '"ndpi" in json_dict and "proto" in json_dict["ndpi"]'
|
||||||
|
# The command above will print only JSONs that have the subobjects json_dict["ndpi"] and json_dict["ndpi"]["proto"] available.
|
||||||
|
# ./examples/py-flow-info/flow-info.py --filter 'json_dict["source"] == "eth0"' --filter '"flow_event_name" in json_dict and json_dict["flow_event_name"] == "analyse"'
|
||||||
|
# Multiple JSON filter will be ANDed together.
|
||||||
|
# Note: You may *only* use the global "json_dict" in your expressions.
|
||||||
|
try:
|
||||||
|
json_filter = args.filter
|
||||||
|
if json_filter is not None:
|
||||||
|
for jf in json_filter:
|
||||||
|
nsock.addFilter(jf)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
global schema
|
||||||
|
schema = {'packet_event_schema' : None, 'error_event_schema' : None, 'daemon_event_schema' : None, 'flow_event_schema' : None}
|
||||||
|
|
||||||
|
def initSchemaValidator(schema_dirs=[]):
|
||||||
|
if len(schema_dirs) == 0:
|
||||||
|
schema_dirs += [os.path.dirname(sys.argv[0]) + '/../../schema']
|
||||||
|
schema_dirs += [os.path.dirname(sys.argv[0]) + '/../share/nDPId']
|
||||||
|
schema_dirs += [sys.base_prefix + '/share/nDPId']
|
||||||
|
|
||||||
def initSchemaValidator(schema_dir='./schema'):
|
|
||||||
for key in schema:
|
for key in schema:
|
||||||
with open(schema_dir + '/' + str(key) + '.json', 'r') as schema_file:
|
for schema_dir in schema_dirs:
|
||||||
schema[key] = json.load(schema_file)
|
try:
|
||||||
|
with open(schema_dir + '/' + str(key) + '.json', 'r') as schema_file:
|
||||||
|
schema[key] = json.load(schema_file)
|
||||||
|
except FileNotFoundError:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
def validateAgainstSchema(json_dict):
|
def validateAgainstSchema(json_dict):
|
||||||
import jsonschema
|
import jsonschema
|
||||||
|
|
||||||
if 'packet_event_id' in json_dict:
|
if 'packet_event_id' in json_dict:
|
||||||
jsonschema.validate(instance=json_dict, schema=schema['packet_event_schema'])
|
try:
|
||||||
|
jsonschema.Draft7Validator(schema=schema['packet_event_schema']).validate(instance=json_dict)
|
||||||
|
except AttributeError:
|
||||||
|
jsonschema.validate(instance=json_dict, schema=schema['packet_event_schema'])
|
||||||
return True
|
return True
|
||||||
if 'basic_event_id' in json_dict:
|
if 'error_event_id' in json_dict:
|
||||||
jsonschema.validate(instance=json_dict, schema=schema['basic_event_schema'])
|
try:
|
||||||
|
jsonschema.Draft7Validator(schema=schema['error_event_schema']).validate(instance=json_dict)
|
||||||
|
except AttributeError:
|
||||||
|
jsonschema.validate(instance=json_dict, schema=schema['error_event_schema'])
|
||||||
return True
|
return True
|
||||||
if 'daemon_event_id' in json_dict:
|
if 'daemon_event_id' in json_dict:
|
||||||
jsonschema.validate(instance=json_dict, schema=schema['daemon_event_schema'])
|
try:
|
||||||
|
jsonschema.Draft7Validator(schema=schema['daemon_event_schema']).validate(instance=json_dict)
|
||||||
|
except AttributeError:
|
||||||
|
jsonschema.validate(instance=json_dict, schema=schema['daemon_event_schema'])
|
||||||
return True
|
return True
|
||||||
if 'flow_event_id' in json_dict:
|
if 'flow_event_id' in json_dict:
|
||||||
jsonschema.validate(instance=json_dict, schema=schema['flow_event_schema'])
|
try:
|
||||||
|
jsonschema.Draft7Validator(schema=schema['flow_event_schema']).validate(instance=json_dict)
|
||||||
|
except AttributeError:
|
||||||
|
jsonschema.validate(instance=json_dict, schema=schema['flow_event_schema'])
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|||||||
41
dependencies/uthash/.github/workflows/build.yml
vendored
Normal file
41
dependencies/uthash/.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
name: build # This name shows up in badge.svg
|
||||||
|
|
||||||
|
on:
|
||||||
|
push: # any branch
|
||||||
|
pull_request:
|
||||||
|
branches: [ "master" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-gcc:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: make -C tests EXTRA_CFLAGS="-W -Wall -Wextra -Wswitch-default"
|
||||||
|
- run: make -C tests clean ; make -C tests pedantic
|
||||||
|
- run: make -C tests clean ; make -C tests pedantic EXTRA_CFLAGS=-DNO_DECLTYPE
|
||||||
|
- run: make -C tests clean ; make -C tests cplusplus
|
||||||
|
- run: make -C tests clean ; make -C tests cplusplus EXTRA_CFLAGS=-DNO_DECLTYPE
|
||||||
|
build-clang:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
CC: clang
|
||||||
|
CXX: clang++
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: make -C tests EXTRA_CFLAGS="-W -Wall -Wextra -Wswitch-default"
|
||||||
|
- run: make -C tests clean ; make -C tests pedantic
|
||||||
|
- run: make -C tests clean ; make -C tests pedantic EXTRA_CFLAGS=-DNO_DECLTYPE
|
||||||
|
- run: make -C tests clean ; make -C tests cplusplus
|
||||||
|
- run: make -C tests clean ; make -C tests cplusplus EXTRA_CFLAGS=-DNO_DECLTYPE
|
||||||
|
build-asciidoc:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: sudo apt-get update && sudo apt-get install asciidoc -y
|
||||||
|
- run: make -C doc
|
||||||
2
dependencies/uthash/.travis.yml
vendored
2
dependencies/uthash/.travis.yml
vendored
@@ -7,7 +7,7 @@ matrix:
|
|||||||
compiler: clang
|
compiler: clang
|
||||||
- os: osx
|
- os: osx
|
||||||
script:
|
script:
|
||||||
- make -C tests EXTRA_CFLAGS="-W -Wall -Wextra"
|
- make -C tests EXTRA_CFLAGS="-W -Wall -Wextra -Wswitch-default"
|
||||||
- make -C tests clean ; make -C tests pedantic
|
- make -C tests clean ; make -C tests pedantic
|
||||||
- make -C tests clean ; make -C tests pedantic EXTRA_CFLAGS=-DNO_DECLTYPE
|
- make -C tests clean ; make -C tests pedantic EXTRA_CFLAGS=-DNO_DECLTYPE
|
||||||
- make -C tests clean ; make -C tests cplusplus
|
- make -C tests clean ; make -C tests cplusplus
|
||||||
|
|||||||
2
dependencies/uthash/LICENSE
vendored
2
dependencies/uthash/LICENSE
vendored
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2005-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
Copyright (c) 2005-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
5
dependencies/uthash/README.md
vendored
5
dependencies/uthash/README.md
vendored
@@ -1,8 +1,9 @@
|
|||||||
|
|
||||||
[](https://travis-ci.org/troydhanson/uthash)
|
[](https://travis-ci.org/troydhanson/uthash)
|
||||||
|
[](https://github.com/troydhanson/uthash/actions/workflows/build.yml)
|
||||||
|
|
||||||
Documentation for uthash is available at:
|
Documentation for uthash is available at:
|
||||||
|
|
||||||
http://troydhanson.github.com/uthash/
|
https://troydhanson.github.io/uthash/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
17
dependencies/uthash/doc/ChangeLog.txt
vendored
17
dependencies/uthash/doc/ChangeLog.txt
vendored
@@ -5,6 +5,21 @@ Click to return to the link:index.html[uthash home page].
|
|||||||
|
|
||||||
NOTE: This ChangeLog may be incomplete and/or incorrect. See the git commit log.
|
NOTE: This ChangeLog may be incomplete and/or incorrect. See the git commit log.
|
||||||
|
|
||||||
|
Version 2.3.0 (2021-02-25)
|
||||||
|
--------------------------
|
||||||
|
* remove HASH_FCN; the HASH_FUNCTION and HASH_KEYCMP macros now behave similarly
|
||||||
|
* remove uthash_memcmp (deprecated in v2.1.0) in favor of HASH_KEYCMP
|
||||||
|
* silence -Wswitch-default warnings (thanks, Olaf Bergmann!)
|
||||||
|
|
||||||
|
Version 2.2.0 (2020-12-17)
|
||||||
|
--------------------------
|
||||||
|
* add HASH_NO_STDINT for platforms without C99 <stdint.h>
|
||||||
|
* silence many -Wcast-qual warnings (thanks, Olaf Bergmann!)
|
||||||
|
* skip hash computation when finding in an empty hash (thanks, Huansong Fu!)
|
||||||
|
* rename oom to utarray_oom, in utarray.h (thanks, Hong Xu!)
|
||||||
|
* rename oom to utstring_oom, in utstring.h (thanks, Hong Xu!)
|
||||||
|
* remove MurmurHash/HASH_MUR
|
||||||
|
|
||||||
Version 2.1.0 (2018-12-20)
|
Version 2.1.0 (2018-12-20)
|
||||||
--------------------------
|
--------------------------
|
||||||
* silence some Clang static analysis warnings
|
* silence some Clang static analysis warnings
|
||||||
@@ -56,7 +71,7 @@ Version 1.9.8 (2013-03-10)
|
|||||||
* `HASH_REPLACE` now in uthash (thanks, Nick Vatamaniuc!)
|
* `HASH_REPLACE` now in uthash (thanks, Nick Vatamaniuc!)
|
||||||
* fixed clang warnings (thanks wynnw!)
|
* fixed clang warnings (thanks wynnw!)
|
||||||
* fixed `utarray_insert` when inserting past array end (thanks Rob Willett!)
|
* fixed `utarray_insert` when inserting past array end (thanks Rob Willett!)
|
||||||
* you can now find http://troydhanson.github.com/uthash/[uthash on GitHub]
|
* you can now find http://troydhanson.github.io/uthash/[uthash on GitHub]
|
||||||
* there's a https://groups.google.com/d/forum/uthash[uthash Google Group]
|
* there's a https://groups.google.com/d/forum/uthash[uthash Google Group]
|
||||||
* uthash has been downloaded 29,000+ times since 2006 on SourceForge
|
* uthash has been downloaded 29,000+ times since 2006 on SourceForge
|
||||||
|
|
||||||
|
|||||||
12
dependencies/uthash/doc/index.html
vendored
12
dependencies/uthash/doc/index.html
vendored
@@ -13,8 +13,8 @@
|
|||||||
</div> <!-- banner -->
|
</div> <!-- banner -->
|
||||||
|
|
||||||
<div id="topnav">
|
<div id="topnav">
|
||||||
<a href="http://github.com/troydhanson/uthash">GitHub page</a> >
|
<a href="https://github.com/troydhanson/uthash">GitHub page</a> >
|
||||||
uthash home <!-- http://troydhanson.github.com/uthash/ -->
|
uthash home <!-- https://troydhanson.github.io/uthash/ -->
|
||||||
|
|
||||||
<a href="https://twitter.com/share" class="twitter-share-button" data-via="troydhanson">Tweet</a>
|
<a href="https://twitter.com/share" class="twitter-share-button" data-via="troydhanson">Tweet</a>
|
||||||
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
|
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<h2>developer</h2>
|
<h2>developer</h2>
|
||||||
<div><a href="http://troydhanson.github.io/">Troy D. Hanson</a></div>
|
<div><a href="https://troydhanson.github.io/">Troy D. Hanson</a></div>
|
||||||
|
|
||||||
<h2>maintainer</h2>
|
<h2>maintainer</h2>
|
||||||
<div><a href="https://github.com/Quuxplusone">Arthur O'Dwyer</a></div>
|
<div><a href="https://github.com/Quuxplusone">Arthur O'Dwyer</a></div>
|
||||||
@@ -72,7 +72,7 @@ struct my_struct {
|
|||||||
struct my_struct *users = NULL;
|
struct my_struct *users = NULL;
|
||||||
|
|
||||||
void add_user(struct my_struct *s) {
|
void add_user(struct my_struct *s) {
|
||||||
HASH_ADD_INT( users, id, s );
|
HASH_ADD_INT(users, id, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
@@ -86,7 +86,7 @@ Example 2. Looking up an item in a hash.
|
|||||||
struct my_struct *find_user(int user_id) {
|
struct my_struct *find_user(int user_id) {
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
HASH_FIND_INT( users, &user_id, s );
|
HASH_FIND_INT(users, &user_id, s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ Example 3. Deleting an item from a hash.
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
void delete_user(struct my_struct *user) {
|
void delete_user(struct my_struct *user) {
|
||||||
HASH_DEL( users, user);
|
HASH_DEL(users, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|||||||
4
dependencies/uthash/doc/license.html
vendored
4
dependencies/uthash/doc/license.html
vendored
@@ -13,7 +13,7 @@
|
|||||||
</div> <!-- banner -->
|
</div> <!-- banner -->
|
||||||
|
|
||||||
<div id="topnav">
|
<div id="topnav">
|
||||||
<a href="http://troydhanson.github.com/uthash/">uthash home</a> >
|
<a href="https://troydhanson.github.io/uthash/">uthash home</a> >
|
||||||
BSD license
|
BSD license
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<div id="mid">
|
<div id="mid">
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<pre>
|
<pre>
|
||||||
Copyright (c) 2005-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
Copyright (c) 2005-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
1
dependencies/uthash/doc/styles.css
vendored
1
dependencies/uthash/doc/styles.css
vendored
@@ -29,7 +29,6 @@ h1,p { margin: 0; } /* non-0 margin on firefox */
|
|||||||
background-repeat: repeat-y;
|
background-repeat: repeat-y;
|
||||||
/* background-color: #ffddaa; */
|
/* background-color: #ffddaa; */
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
padding-top: 20px;
|
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
266
dependencies/uthash/doc/userguide.txt
vendored
266
dependencies/uthash/doc/userguide.txt
vendored
@@ -1,11 +1,11 @@
|
|||||||
uthash User Guide
|
uthash User Guide
|
||||||
=================
|
=================
|
||||||
Troy D. Hanson, Arthur O'Dwyer
|
Troy D. Hanson, Arthur O'Dwyer
|
||||||
v2.1.0, December 2018
|
v2.3.0, February 2021
|
||||||
|
|
||||||
To download uthash, follow this link back to the
|
To download uthash, follow this link back to the
|
||||||
https://github.com/troydhanson/uthash[GitHub project page].
|
https://github.com/troydhanson/uthash[GitHub project page].
|
||||||
Back to my http://troydhanson.github.io/[other projects].
|
Back to my https://troydhanson.github.io/[other projects].
|
||||||
|
|
||||||
A hash in C
|
A hash in C
|
||||||
-----------
|
-----------
|
||||||
@@ -215,10 +215,10 @@ a unique value. Then call `HASH_ADD`. (Here we use the convenience macro
|
|||||||
void add_user(int user_id, char *name) {
|
void add_user(int user_id, char *name) {
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
s = malloc(sizeof(struct my_struct));
|
s = malloc(sizeof *s);
|
||||||
s->id = user_id;
|
s->id = user_id;
|
||||||
strcpy(s->name, name);
|
strcpy(s->name, name);
|
||||||
HASH_ADD_INT( users, id, s ); /* id: name of key field */
|
HASH_ADD_INT(users, id, s); /* id: name of key field */
|
||||||
}
|
}
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ second parameter is the 'name' of the key field. Here, this is `id`. The
|
|||||||
last parameter is a pointer to the structure being added.
|
last parameter is a pointer to the structure being added.
|
||||||
|
|
||||||
[[validc]]
|
[[validc]]
|
||||||
.Wait.. the field name is a parameter?
|
.Wait.. the parameter is a field name?
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
If you find it strange that `id`, which is the 'name of a field' in the
|
If you find it strange that `id`, which is the 'name of a field' in the
|
||||||
structure, can be passed as a parameter... welcome to the world of macros. Don't
|
structure, can be passed as a parameter... welcome to the world of macros. Don't
|
||||||
@@ -256,10 +256,10 @@ Otherwise we just modify the structure that already exists.
|
|||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */
|
HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */
|
||||||
if (s==NULL) {
|
if (s == NULL) {
|
||||||
s = (struct my_struct *)malloc(sizeof *s);
|
s = (struct my_struct *)malloc(sizeof *s);
|
||||||
s->id = user_id;
|
s->id = user_id;
|
||||||
HASH_ADD_INT( users, id, s ); /* id: name of key field */
|
HASH_ADD_INT(users, id, s); /* id: name of key field */
|
||||||
}
|
}
|
||||||
strcpy(s->name, name);
|
strcpy(s->name, name);
|
||||||
}
|
}
|
||||||
@@ -284,7 +284,7 @@ right.
|
|||||||
/* bad */
|
/* bad */
|
||||||
void add_user(struct my_struct *users, int user_id, char *name) {
|
void add_user(struct my_struct *users, int user_id, char *name) {
|
||||||
...
|
...
|
||||||
HASH_ADD_INT( users, id, s );
|
HASH_ADD_INT(users, id, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
You really need to pass 'a pointer' to the hash pointer:
|
You really need to pass 'a pointer' to the hash pointer:
|
||||||
@@ -292,7 +292,7 @@ You really need to pass 'a pointer' to the hash pointer:
|
|||||||
/* good */
|
/* good */
|
||||||
void add_user(struct my_struct **users, int user_id, char *name) { ...
|
void add_user(struct my_struct **users, int user_id, char *name) { ...
|
||||||
...
|
...
|
||||||
HASH_ADD_INT( *users, id, s );
|
HASH_ADD_INT(*users, id, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Note that we dereferenced the pointer in the `HASH_ADD` also.
|
Note that we dereferenced the pointer in the `HASH_ADD` also.
|
||||||
@@ -319,7 +319,7 @@ To look up a structure in a hash, you need its key. Then call `HASH_FIND`.
|
|||||||
struct my_struct *find_user(int user_id) {
|
struct my_struct *find_user(int user_id) {
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */
|
HASH_FIND_INT(users, &user_id, s); /* s: output pointer */
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
@@ -376,8 +376,8 @@ void delete_all() {
|
|||||||
struct my_struct *current_user, *tmp;
|
struct my_struct *current_user, *tmp;
|
||||||
|
|
||||||
HASH_ITER(hh, users, current_user, tmp) {
|
HASH_ITER(hh, users, current_user, tmp) {
|
||||||
HASH_DEL(users,current_user); /* delete; users advances to next */
|
HASH_DEL(users, current_user); /* delete; users advances to next */
|
||||||
free(current_user); /* optional- if you want to free */
|
free(current_user); /* optional- if you want to free */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
@@ -387,7 +387,7 @@ All-at-once deletion
|
|||||||
If you only want to delete all the items, but not free them or do any
|
If you only want to delete all the items, but not free them or do any
|
||||||
per-element clean up, you can do this more efficiently in a single operation:
|
per-element clean up, you can do this more efficiently in a single operation:
|
||||||
|
|
||||||
HASH_CLEAR(hh,users);
|
HASH_CLEAR(hh, users);
|
||||||
|
|
||||||
Afterward, the list head (here, `users`) will be set to `NULL`.
|
Afterward, the list head (here, `users`) will be set to `NULL`.
|
||||||
|
|
||||||
@@ -403,7 +403,7 @@ num_users = HASH_COUNT(users);
|
|||||||
printf("there are %u users\n", num_users);
|
printf("there are %u users\n", num_users);
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
Incidentally, this works even the list (`users`, here) is `NULL`, in
|
Incidentally, this works even if the list head (here, `users`) is `NULL`, in
|
||||||
which case the count is 0.
|
which case the count is 0.
|
||||||
|
|
||||||
Iterating and sorting
|
Iterating and sorting
|
||||||
@@ -417,7 +417,7 @@ following the `hh.next` pointer.
|
|||||||
void print_users() {
|
void print_users() {
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
for(s=users; s != NULL; s=s->hh.next) {
|
for (s = users; s != NULL; s = s->hh.next) {
|
||||||
printf("user id %d: name %s\n", s->id, s->name);
|
printf("user id %d: name %s\n", s->id, s->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,7 +430,7 @@ the hash, starting from any known item.
|
|||||||
Deletion-safe iteration
|
Deletion-safe iteration
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
In the example above, it would not be safe to delete and free `s` in the body
|
In the example above, it would not be safe to delete and free `s` in the body
|
||||||
of the 'for' loop, (because `s` is derefenced each time the loop iterates).
|
of the 'for' loop, (because `s` is dereferenced each time the loop iterates).
|
||||||
This is easy to rewrite correctly (by copying the `s->hh.next` pointer to a
|
This is easy to rewrite correctly (by copying the `s->hh.next` pointer to a
|
||||||
temporary variable 'before' freeing `s`), but it comes up often enough that a
|
temporary variable 'before' freeing `s`), but it comes up often enough that a
|
||||||
deletion-safe iteration macro, `HASH_ITER`, is included. It expands to a
|
deletion-safe iteration macro, `HASH_ITER`, is included. It expands to a
|
||||||
@@ -452,14 +452,14 @@ doubly-linked list.
|
|||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
|
|
||||||
If you're using uthash in a C++ program, you need an extra cast on the `for`
|
If you're using uthash in a C++ program, you need an extra cast on the `for`
|
||||||
iterator, e.g., `s=(struct my_struct*)s->hh.next`.
|
iterator, e.g., `s = static_cast<my_struct*>(s->hh.next)`.
|
||||||
|
|
||||||
Sorting
|
Sorting
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
The items in the hash are visited in "insertion order" when you follow the
|
The items in the hash are visited in "insertion order" when you follow the
|
||||||
`hh.next` pointer. You can sort the items into a new order using `HASH_SORT`.
|
`hh.next` pointer. You can sort the items into a new order using `HASH_SORT`.
|
||||||
|
|
||||||
HASH_SORT( users, name_sort );
|
HASH_SORT(users, name_sort);
|
||||||
|
|
||||||
The second argument is a pointer to a comparison function. It must accept two
|
The second argument is a pointer to a comparison function. It must accept two
|
||||||
pointer arguments (the items to compare), and must return an `int` which is
|
pointer arguments (the items to compare), and must return an `int` which is
|
||||||
@@ -479,20 +479,20 @@ Below, `name_sort` and `id_sort` are two examples of sort functions.
|
|||||||
|
|
||||||
.Sorting the items in the hash
|
.Sorting the items in the hash
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
int name_sort(struct my_struct *a, struct my_struct *b) {
|
int by_name(const struct my_struct *a, const struct my_struct *b) {
|
||||||
return strcmp(a->name,b->name);
|
return strcmp(a->name, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int id_sort(struct my_struct *a, struct my_struct *b) {
|
int by_id(const struct my_struct *a, const struct my_struct *b) {
|
||||||
return (a->id - b->id);
|
return (a->id - b->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_by_name() {
|
void sort_by_name() {
|
||||||
HASH_SORT(users, name_sort);
|
HASH_SORT(users, by_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_by_id() {
|
void sort_by_id() {
|
||||||
HASH_SORT(users, id_sort);
|
HASH_SORT(users, by_id);
|
||||||
}
|
}
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -516,85 +516,100 @@ Follow the prompts to try the program.
|
|||||||
|
|
||||||
.A complete program
|
.A complete program
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
#include <stdio.h> /* gets */
|
#include <stdio.h> /* printf */
|
||||||
#include <stdlib.h> /* atoi, malloc */
|
#include <stdlib.h> /* atoi, malloc */
|
||||||
#include <string.h> /* strcpy */
|
#include <string.h> /* strcpy */
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
|
||||||
struct my_struct {
|
struct my_struct {
|
||||||
int id; /* key */
|
int id; /* key */
|
||||||
char name[10];
|
char name[21];
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
UT_hash_handle hh; /* makes this structure hashable */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct my_struct *users = NULL;
|
struct my_struct *users = NULL;
|
||||||
|
|
||||||
void add_user(int user_id, char *name) {
|
void add_user(int user_id, const char *name)
|
||||||
|
{
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */
|
HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */
|
||||||
if (s==NULL) {
|
if (s == NULL) {
|
||||||
s = (struct my_struct *)malloc(sizeof *s);
|
s = (struct my_struct*)malloc(sizeof *s);
|
||||||
s->id = user_id;
|
s->id = user_id;
|
||||||
HASH_ADD_INT( users, id, s ); /* id: name of key field */
|
HASH_ADD_INT(users, id, s); /* id is the key field */
|
||||||
}
|
}
|
||||||
strcpy(s->name, name);
|
strcpy(s->name, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct my_struct *find_user(int user_id) {
|
struct my_struct *find_user(int user_id)
|
||||||
|
{
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */
|
HASH_FIND_INT(users, &user_id, s); /* s: output pointer */
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_user(struct my_struct *user) {
|
void delete_user(struct my_struct *user)
|
||||||
|
{
|
||||||
HASH_DEL(users, user); /* user: pointer to deletee */
|
HASH_DEL(users, user); /* user: pointer to deletee */
|
||||||
free(user);
|
free(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_all() {
|
void delete_all()
|
||||||
struct my_struct *current_user, *tmp;
|
{
|
||||||
|
struct my_struct *current_user;
|
||||||
|
struct my_struct *tmp;
|
||||||
|
|
||||||
HASH_ITER(hh, users, current_user, tmp) {
|
HASH_ITER(hh, users, current_user, tmp) {
|
||||||
HASH_DEL(users, current_user); /* delete it (users advances to next) */
|
HASH_DEL(users, current_user); /* delete it (users advances to next) */
|
||||||
free(current_user); /* free it */
|
free(current_user); /* free it */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_users() {
|
void print_users()
|
||||||
|
{
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
for(s=users; s != NULL; s=(struct my_struct*)(s->hh.next)) {
|
for (s = users; s != NULL; s = (struct my_struct*)(s->hh.next)) {
|
||||||
printf("user id %d: name %s\n", s->id, s->name);
|
printf("user id %d: name %s\n", s->id, s->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int name_sort(struct my_struct *a, struct my_struct *b) {
|
int by_name(const struct my_struct *a, const struct my_struct *b)
|
||||||
return strcmp(a->name,b->name);
|
{
|
||||||
|
return strcmp(a->name, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int id_sort(struct my_struct *a, struct my_struct *b) {
|
int by_id(const struct my_struct *a, const struct my_struct *b)
|
||||||
|
{
|
||||||
return (a->id - b->id);
|
return (a->id - b->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_by_name() {
|
const char *getl(const char *prompt)
|
||||||
HASH_SORT(users, name_sort);
|
{
|
||||||
|
static char buf[21];
|
||||||
|
char *p;
|
||||||
|
printf("%s? ", prompt); fflush(stdout);
|
||||||
|
p = fgets(buf, sizeof(buf), stdin);
|
||||||
|
if (p == NULL || (p = strchr(buf, '\n')) == NULL) {
|
||||||
|
puts("Invalid input!");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_by_id() {
|
int main()
|
||||||
HASH_SORT(users, id_sort);
|
{
|
||||||
}
|
int id = 1;
|
||||||
|
int running = 1;
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
char in[10];
|
|
||||||
int id=1, running=1;
|
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
unsigned num_users;
|
int temp;
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
printf(" 1. add user\n");
|
printf(" 1. add user\n");
|
||||||
printf(" 2. add/rename user by id\n");
|
printf(" 2. add or rename user by id\n");
|
||||||
printf(" 3. find user\n");
|
printf(" 3. find user\n");
|
||||||
printf(" 4. delete user\n");
|
printf(" 4. delete user\n");
|
||||||
printf(" 5. delete all users\n");
|
printf(" 5. delete all users\n");
|
||||||
@@ -603,47 +618,44 @@ int main(int argc, char *argv[]) {
|
|||||||
printf(" 8. print users\n");
|
printf(" 8. print users\n");
|
||||||
printf(" 9. count users\n");
|
printf(" 9. count users\n");
|
||||||
printf("10. quit\n");
|
printf("10. quit\n");
|
||||||
gets(in);
|
switch (atoi(getl("Command"))) {
|
||||||
switch(atoi(in)) {
|
|
||||||
case 1:
|
case 1:
|
||||||
printf("name?\n");
|
add_user(id++, getl("Name (20 char max)"));
|
||||||
add_user(id++, gets(in));
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
printf("id?\n");
|
temp = atoi(getl("ID"));
|
||||||
gets(in); id = atoi(in);
|
add_user(temp, getl("Name (20 char max)"));
|
||||||
printf("name?\n");
|
|
||||||
add_user(id, gets(in));
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
printf("id?\n");
|
s = find_user(atoi(getl("ID to find")));
|
||||||
s = find_user(atoi(gets(in)));
|
|
||||||
printf("user: %s\n", s ? s->name : "unknown");
|
printf("user: %s\n", s ? s->name : "unknown");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
printf("id?\n");
|
s = find_user(atoi(getl("ID to delete")));
|
||||||
s = find_user(atoi(gets(in)));
|
if (s) {
|
||||||
if (s) delete_user(s);
|
delete_user(s);
|
||||||
else printf("id unknown\n");
|
} else {
|
||||||
|
printf("id unknown\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
delete_all();
|
delete_all();
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
sort_by_name();
|
HASH_SORT(users, by_name);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
sort_by_id();
|
HASH_SORT(users, by_id);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
print_users();
|
print_users();
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
num_users=HASH_COUNT(users);
|
temp = HASH_COUNT(users);
|
||||||
printf("there are %u users\n", num_users);
|
printf("there are %d users\n", temp);
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
running=0;
|
running = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -720,10 +732,10 @@ int main(int argc, char *argv[]) {
|
|||||||
s = (struct my_struct *)malloc(sizeof *s);
|
s = (struct my_struct *)malloc(sizeof *s);
|
||||||
strcpy(s->name, names[i]);
|
strcpy(s->name, names[i]);
|
||||||
s->id = i;
|
s->id = i;
|
||||||
HASH_ADD_STR( users, name, s );
|
HASH_ADD_STR(users, name, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
HASH_FIND_STR( users, "betty", s);
|
HASH_FIND_STR(users, "betty", s);
|
||||||
if (s) printf("betty's id is %d\n", s->id);
|
if (s) printf("betty's id is %d\n", s->id);
|
||||||
|
|
||||||
/* free the hash table contents */
|
/* free the hash table contents */
|
||||||
@@ -766,10 +778,10 @@ int main(int argc, char *argv[]) {
|
|||||||
s = (struct my_struct *)malloc(sizeof *s);
|
s = (struct my_struct *)malloc(sizeof *s);
|
||||||
s->name = names[i];
|
s->name = names[i];
|
||||||
s->id = i;
|
s->id = i;
|
||||||
HASH_ADD_KEYPTR( hh, users, s->name, strlen(s->name), s );
|
HASH_ADD_KEYPTR(hh, users, s->name, strlen(s->name), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
HASH_FIND_STR( users, "betty", s);
|
HASH_FIND_STR(users, "betty", s);
|
||||||
if (s) printf("betty's id is %d\n", s->id);
|
if (s) printf("betty's id is %d\n", s->id);
|
||||||
|
|
||||||
/* free the hash table contents */
|
/* free the hash table contents */
|
||||||
@@ -793,7 +805,7 @@ Here is a simple example where a structure has a pointer member, called `key`.
|
|||||||
|
|
||||||
.A pointer key
|
.A pointer key
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
#include <stdio.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
|
||||||
@@ -804,28 +816,25 @@ typedef struct {
|
|||||||
} el_t;
|
} el_t;
|
||||||
|
|
||||||
el_t *hash = NULL;
|
el_t *hash = NULL;
|
||||||
char *someaddr = NULL;
|
void *someaddr = &hash;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
el_t *d;
|
el_t *d;
|
||||||
el_t *e = (el_t *)malloc(sizeof *e);
|
el_t *e = (el_t *)malloc(sizeof *e);
|
||||||
if (!e) return -1;
|
e->key = someaddr;
|
||||||
e->key = (void*)someaddr;
|
|
||||||
e->i = 1;
|
e->i = 1;
|
||||||
HASH_ADD_PTR(hash,key,e);
|
HASH_ADD_PTR(hash, key, e);
|
||||||
HASH_FIND_PTR(hash, &someaddr, d);
|
HASH_FIND_PTR(hash, &someaddr, d);
|
||||||
if (d) printf("found\n");
|
assert(d == e);
|
||||||
|
|
||||||
/* release memory */
|
/* release memory */
|
||||||
HASH_DEL(hash,e);
|
HASH_DEL(hash, e);
|
||||||
free(e);
|
free(e);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
This example is included in `tests/test57.c`. Note that the end of the program
|
This example is included in `tests/test57.c`.
|
||||||
deletes the element out of the hash, (and since no more elements remain in the
|
|
||||||
hash), uthash releases its internal memory.
|
|
||||||
|
|
||||||
Structure keys
|
Structure keys
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
@@ -881,7 +890,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
This usage is nearly the same as use of a compound key explained below.
|
This usage is nearly the same as the usage of a compound key explained below.
|
||||||
|
|
||||||
Note that the general macros require the name of the `UT_hash_handle` to be
|
Note that the general macros require the name of the `UT_hash_handle` to be
|
||||||
passed as the first argument (here, this is `hh`). The general macros are
|
passed as the first argument (here, this is `hh`). The general macros are
|
||||||
@@ -924,7 +933,7 @@ int main(int argc, char *argv[]) {
|
|||||||
int beijing[] = {0x5317, 0x4eac}; /* UTF-32LE for 北京 */
|
int beijing[] = {0x5317, 0x4eac}; /* UTF-32LE for 北京 */
|
||||||
|
|
||||||
/* allocate and initialize our structure */
|
/* allocate and initialize our structure */
|
||||||
msg = (msg_t *)malloc( sizeof(msg_t) + sizeof(beijing) );
|
msg = (msg_t *)malloc(sizeof(msg_t) + sizeof(beijing));
|
||||||
memset(msg, 0, sizeof(msg_t)+sizeof(beijing)); /* zero fill */
|
memset(msg, 0, sizeof(msg_t)+sizeof(beijing)); /* zero fill */
|
||||||
msg->len = sizeof(beijing);
|
msg->len = sizeof(beijing);
|
||||||
msg->encoding = UTF32;
|
msg->encoding = UTF32;
|
||||||
@@ -936,16 +945,16 @@ int main(int argc, char *argv[]) {
|
|||||||
- offsetof(msg_t, encoding); /* offset of first key field */
|
- offsetof(msg_t, encoding); /* offset of first key field */
|
||||||
|
|
||||||
/* add our structure to the hash table */
|
/* add our structure to the hash table */
|
||||||
HASH_ADD( hh, msgs, encoding, keylen, msg);
|
HASH_ADD(hh, msgs, encoding, keylen, msg);
|
||||||
|
|
||||||
/* look it up to prove that it worked :-) */
|
/* look it up to prove that it worked :-) */
|
||||||
msg=NULL;
|
msg = NULL;
|
||||||
|
|
||||||
lookup_key = (lookup_key_t *)malloc(sizeof(*lookup_key) + sizeof(beijing));
|
lookup_key = (lookup_key_t *)malloc(sizeof(*lookup_key) + sizeof(beijing));
|
||||||
memset(lookup_key, 0, sizeof(*lookup_key) + sizeof(beijing));
|
memset(lookup_key, 0, sizeof(*lookup_key) + sizeof(beijing));
|
||||||
lookup_key->encoding = UTF32;
|
lookup_key->encoding = UTF32;
|
||||||
memcpy(lookup_key->text, beijing, sizeof(beijing));
|
memcpy(lookup_key->text, beijing, sizeof(beijing));
|
||||||
HASH_FIND( hh, msgs, &lookup_key->encoding, keylen, msg );
|
HASH_FIND(hh, msgs, &lookup_key->encoding, keylen, msg);
|
||||||
if (msg) printf("found \n");
|
if (msg) printf("found \n");
|
||||||
free(lookup_key);
|
free(lookup_key);
|
||||||
|
|
||||||
@@ -1028,7 +1037,7 @@ typedef struct item {
|
|||||||
UT_hash_handle hh;
|
UT_hash_handle hh;
|
||||||
} item_t;
|
} item_t;
|
||||||
|
|
||||||
item_t *items=NULL;
|
item_t *items = NULL;
|
||||||
|
|
||||||
int main(int argc, char *argvp[]) {
|
int main(int argc, char *argvp[]) {
|
||||||
item_t *item1, *item2, *tmp1, *tmp2;
|
item_t *item1, *item2, *tmp1, *tmp2;
|
||||||
@@ -1119,7 +1128,7 @@ always used with the `users_by_name` hash table).
|
|||||||
int i;
|
int i;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
s = malloc(sizeof(struct my_struct));
|
s = malloc(sizeof *s);
|
||||||
s->id = 1;
|
s->id = 1;
|
||||||
strcpy(s->username, "thanson");
|
strcpy(s->username, "thanson");
|
||||||
|
|
||||||
@@ -1128,7 +1137,7 @@ always used with the `users_by_name` hash table).
|
|||||||
HASH_ADD(hh2, users_by_name, username, strlen(s->username), s);
|
HASH_ADD(hh2, users_by_name, username, strlen(s->username), s);
|
||||||
|
|
||||||
/* find user by ID in the "users_by_id" hash table */
|
/* find user by ID in the "users_by_id" hash table */
|
||||||
i=1;
|
i = 1;
|
||||||
HASH_FIND(hh1, users_by_id, &i, sizeof(int), s);
|
HASH_FIND(hh1, users_by_id, &i, sizeof(int), s);
|
||||||
if (s) printf("found id %d: %s\n", i, s->username);
|
if (s) printf("found id %d: %s\n", i, s->username);
|
||||||
|
|
||||||
@@ -1141,30 +1150,29 @@ always used with the `users_by_name` hash table).
|
|||||||
|
|
||||||
Sorted insertion of new items
|
Sorted insertion of new items
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
If you would like to maintain a sorted hash you have two options. The first
|
To maintain a sorted hash, you have two options. Your first
|
||||||
option is to use the HASH_SRT() macro, which will sort any unordered list in
|
option is to use the `HASH_SRT` macro, which will sort any unordered list in
|
||||||
'O(n log(n))'. This is the best strategy if you're just filling up a hash
|
'O(n log(n))'. This is the best strategy if you're just filling up a hash
|
||||||
table with items in random order with a single final HASH_SRT() operation
|
table with items in random order with a single final `HASH_SRT` operation
|
||||||
when all is done. Obviously, this won't do what you want if you need
|
when all is done. If you need the table to remain sorted as you add and remove
|
||||||
the list to be in an ordered state at times between insertion of
|
items, you can use `HASH_SRT` after every insertion operation, but that gives
|
||||||
items. You can use HASH_SRT() after every insertion operation, but that will
|
a computational complexity of 'O(n^2 log n)' to insert 'n' items.
|
||||||
yield a computational complexity of 'O(n^2 log n)'.
|
|
||||||
|
|
||||||
The second route you can take is via the in-order add and replace macros.
|
Your second option is to use the in-order add and replace macros.
|
||||||
The `HASH_ADD_INORDER*` macros work just like their `HASH_ADD*` counterparts, but
|
The `HASH_ADD_*_INORDER` macros work just like their `HASH_ADD_*` counterparts, but
|
||||||
with an additional comparison-function argument:
|
with an additional comparison-function argument:
|
||||||
|
|
||||||
int name_sort(struct my_struct *a, struct my_struct *b) {
|
int name_sort(struct my_struct *a, struct my_struct *b) {
|
||||||
return strcmp(a->name,b->name);
|
return strcmp(a->name, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
HASH_ADD_KEYPTR_INORDER(hh, items, &item->name, strlen(item->name), item, name_sort);
|
HASH_ADD_KEYPTR_INORDER(hh, items, &item->name, strlen(item->name), item, name_sort);
|
||||||
|
|
||||||
New items are sorted at insertion time in 'O(n)', thus resulting in a
|
These macros assume that the hash is already sorted according to the
|
||||||
total computational complexity of 'O(n^2)' for the creation of the hash
|
comparison function, and insert the new item in its proper place.
|
||||||
table with all items.
|
A single insertion takes 'O(n)', resulting in a total computational
|
||||||
For in-order add to work, the list must be in an ordered state before
|
complexity of 'O(n^2)' to insert all 'n' items: slower than a single
|
||||||
insertion of the new item.
|
`HASH_SRT`, but faster than doing a `HASH_SRT` after every insertion.
|
||||||
|
|
||||||
Several sort orders
|
Several sort orders
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
@@ -1183,7 +1191,7 @@ Now we can define two sort functions, then use `HASH_SRT`.
|
|||||||
}
|
}
|
||||||
|
|
||||||
int sort_by_name(struct my_struct *a, struct my_struct *b) {
|
int sort_by_name(struct my_struct *a, struct my_struct *b) {
|
||||||
return strcmp(a->username,b->username);
|
return strcmp(a->username, b->username);
|
||||||
}
|
}
|
||||||
|
|
||||||
HASH_SRT(hh1, users_by_id, sort_by_id);
|
HASH_SRT(hh1, users_by_id, sort_by_id);
|
||||||
@@ -1240,7 +1248,8 @@ for a structure to be usable with `HASH_SELECT`, it must have two or more hash
|
|||||||
handles. (As described <<multihash,here>>, a structure can exist in many
|
handles. (As described <<multihash,here>>, a structure can exist in many
|
||||||
hash tables at the same time; it must have a separate hash handle for each one).
|
hash tables at the same time; it must have a separate hash handle for each one).
|
||||||
|
|
||||||
user_t *users=NULL, *admins=NULL; /* two hash tables */
|
user_t *users = NULL; /* hash table of users */
|
||||||
|
user_t *admins = NULL; /* hash table of admins */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int id;
|
int id;
|
||||||
@@ -1252,25 +1261,26 @@ Now suppose we have added some users, and want to select just the administrator
|
|||||||
users who have id's less than 1024.
|
users who have id's less than 1024.
|
||||||
|
|
||||||
#define is_admin(x) (((user_t*)x)->id < 1024)
|
#define is_admin(x) (((user_t*)x)->id < 1024)
|
||||||
HASH_SELECT(ah,admins,hh,users,is_admin);
|
HASH_SELECT(ah, admins, hh, users, is_admin);
|
||||||
|
|
||||||
The first two parameters are the 'destination' hash handle and hash table, the
|
The first two parameters are the 'destination' hash handle and hash table, the
|
||||||
second two parameters are the 'source' hash handle and hash table, and the last
|
second two parameters are the 'source' hash handle and hash table, and the last
|
||||||
parameter is the 'select condition'. Here we used a macro `is_admin()` but we
|
parameter is the 'select condition'. Here we used a macro `is_admin(x)` but we
|
||||||
could just as well have used a function.
|
could just as well have used a function.
|
||||||
|
|
||||||
int is_admin(void *userv) {
|
int is_admin(const void *userv) {
|
||||||
user_t *user = (user_t*)userv;
|
user_t *user = (const user_t*)userv;
|
||||||
return (user->id < 1024) ? 1 : 0;
|
return (user->id < 1024) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
If the select condition always evaluates to true, this operation is
|
If the select condition always evaluates to true, this operation is
|
||||||
essentially a 'merge' of the source hash into the destination hash. Of course,
|
essentially a 'merge' of the source hash into the destination hash.
|
||||||
the source hash remains unchanged under any use of `HASH_SELECT`. It only adds
|
|
||||||
items to the destination hash selectively.
|
|
||||||
|
|
||||||
The two hash handles must differ. An example of using `HASH_SELECT` is included
|
`HASH_SELECT` adds items to the destination without removing them from
|
||||||
in `tests/test36.c`.
|
the source; the source hash table remains unchanged. The destination hash table
|
||||||
|
must not be the same as the source hash table.
|
||||||
|
|
||||||
|
An example of using `HASH_SELECT` is included in `tests/test36.c`.
|
||||||
|
|
||||||
[[hash_keycompare]]
|
[[hash_keycompare]]
|
||||||
Specifying an alternate key comparison function
|
Specifying an alternate key comparison function
|
||||||
@@ -1290,7 +1300,7 @@ that do not provide `memcmp`, you can substitute your own implementation.
|
|||||||
|
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
#undef HASH_KEYCMP
|
#undef HASH_KEYCMP
|
||||||
#define HASH_KEYCMP(a,b,len) bcmp(a,b,len)
|
#define HASH_KEYCMP(a,b,len) bcmp(a, b, len)
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
Another reason to substitute your own key comparison function is if your "key" is not
|
Another reason to substitute your own key comparison function is if your "key" is not
|
||||||
@@ -1631,7 +1641,7 @@ If your application uses its own custom allocator, uthash can use them too.
|
|||||||
|
|
||||||
/* re-define, specifying alternate functions */
|
/* re-define, specifying alternate functions */
|
||||||
#define uthash_malloc(sz) my_malloc(sz)
|
#define uthash_malloc(sz) my_malloc(sz)
|
||||||
#define uthash_free(ptr,sz) my_free(ptr)
|
#define uthash_free(ptr, sz) my_free(ptr)
|
||||||
|
|
||||||
...
|
...
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
@@ -1647,7 +1657,7 @@ provide these functions, you can substitute your own implementations.
|
|||||||
|
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
#undef uthash_bzero
|
#undef uthash_bzero
|
||||||
#define uthash_bzero(a,len) my_bzero(a,len)
|
#define uthash_bzero(a, len) my_bzero(a, len)
|
||||||
|
|
||||||
#undef uthash_strlen
|
#undef uthash_strlen
|
||||||
#define uthash_strlen(s) my_strlen(s)
|
#define uthash_strlen(s) my_strlen(s)
|
||||||
@@ -1754,7 +1764,7 @@ concurrent readers (since uthash 1.5).
|
|||||||
For example using pthreads you can create an rwlock like this:
|
For example using pthreads you can create an rwlock like this:
|
||||||
|
|
||||||
pthread_rwlock_t lock;
|
pthread_rwlock_t lock;
|
||||||
if (pthread_rwlock_init(&lock,NULL) != 0) fatal("can't create rwlock");
|
if (pthread_rwlock_init(&lock, NULL) != 0) fatal("can't create rwlock");
|
||||||
|
|
||||||
Then, readers must acquire the read lock before doing any `HASH_FIND` calls or
|
Then, readers must acquire the read lock before doing any `HASH_FIND` calls or
|
||||||
before iterating over the hash elements:
|
before iterating over the hash elements:
|
||||||
@@ -1795,10 +1805,10 @@ In order to use the convenience macros,
|
|||||||
|===============================================================================
|
|===============================================================================
|
||||||
|macro | arguments
|
|macro | arguments
|
||||||
|HASH_ADD_INT | (head, keyfield_name, item_ptr)
|
|HASH_ADD_INT | (head, keyfield_name, item_ptr)
|
||||||
|HASH_REPLACE_INT | (head, keyfiled_name, item_ptr,replaced_item_ptr)
|
|HASH_REPLACE_INT | (head, keyfield_name, item_ptr, replaced_item_ptr)
|
||||||
|HASH_FIND_INT | (head, key_ptr, item_ptr)
|
|HASH_FIND_INT | (head, key_ptr, item_ptr)
|
||||||
|HASH_ADD_STR | (head, keyfield_name, item_ptr)
|
|HASH_ADD_STR | (head, keyfield_name, item_ptr)
|
||||||
|HASH_REPLACE_STR | (head,keyfield_name, item_ptr, replaced_item_ptr)
|
|HASH_REPLACE_STR | (head, keyfield_name, item_ptr, replaced_item_ptr)
|
||||||
|HASH_FIND_STR | (head, key_ptr, item_ptr)
|
|HASH_FIND_STR | (head, key_ptr, item_ptr)
|
||||||
|HASH_ADD_PTR | (head, keyfield_name, item_ptr)
|
|HASH_ADD_PTR | (head, keyfield_name, item_ptr)
|
||||||
|HASH_REPLACE_PTR | (head, keyfield_name, item_ptr, replaced_item_ptr)
|
|HASH_REPLACE_PTR | (head, keyfield_name, item_ptr, replaced_item_ptr)
|
||||||
|
|||||||
4
dependencies/uthash/doc/utarray.txt
vendored
4
dependencies/uthash/doc/utarray.txt
vendored
@@ -1,7 +1,7 @@
|
|||||||
utarray: dynamic array macros for C
|
utarray: dynamic array macros for C
|
||||||
===================================
|
===================================
|
||||||
Troy D. Hanson <tdh@tkhanson.net>
|
Troy D. Hanson <tdh@tkhanson.net>
|
||||||
v2.1.0, December 2018
|
v2.3.0, February 2021
|
||||||
|
|
||||||
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
|
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ a copy of the source string and pushes that copy into the array.
|
|||||||
About UT_icd
|
About UT_icd
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
Arrays be made of any type of element, not just integers and strings. The
|
Arrays can be made of any type of element, not just integers and strings. The
|
||||||
elements can be basic types or structures. Unless you're dealing with integers
|
elements can be basic types or structures. Unless you're dealing with integers
|
||||||
and strings (which use pre-defined `ut_int_icd` and `ut_str_icd`), you'll need
|
and strings (which use pre-defined `ut_int_icd` and `ut_str_icd`), you'll need
|
||||||
to define a `UT_icd` helper structure. This structure contains everything that
|
to define a `UT_icd` helper structure. This structure contains everything that
|
||||||
|
|||||||
2
dependencies/uthash/doc/utlist.txt
vendored
2
dependencies/uthash/doc/utlist.txt
vendored
@@ -1,7 +1,7 @@
|
|||||||
utlist: linked list macros for C structures
|
utlist: linked list macros for C structures
|
||||||
===========================================
|
===========================================
|
||||||
Troy D. Hanson <tdh@tkhanson.net>
|
Troy D. Hanson <tdh@tkhanson.net>
|
||||||
v2.1.0, December 2018
|
v2.3.0, February 2021
|
||||||
|
|
||||||
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
|
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
|
||||||
|
|
||||||
|
|||||||
2
dependencies/uthash/doc/utringbuffer.txt
vendored
2
dependencies/uthash/doc/utringbuffer.txt
vendored
@@ -1,7 +1,7 @@
|
|||||||
utringbuffer: dynamic ring-buffer macros for C
|
utringbuffer: dynamic ring-buffer macros for C
|
||||||
==============================================
|
==============================================
|
||||||
Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
|
Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
|
||||||
v2.1.0, December 2018
|
v2.3.0, February 2021
|
||||||
|
|
||||||
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
|
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
|
||||||
|
|
||||||
|
|||||||
2
dependencies/uthash/doc/utstack.txt
vendored
2
dependencies/uthash/doc/utstack.txt
vendored
@@ -1,7 +1,7 @@
|
|||||||
utstack: intrusive stack macros for C
|
utstack: intrusive stack macros for C
|
||||||
=====================================
|
=====================================
|
||||||
Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
|
Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
|
||||||
v2.1.0, December 2018
|
v2.3.0, February 2021
|
||||||
|
|
||||||
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
|
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
|
||||||
|
|
||||||
|
|||||||
2
dependencies/uthash/doc/utstring.txt
vendored
2
dependencies/uthash/doc/utstring.txt
vendored
@@ -1,7 +1,7 @@
|
|||||||
utstring: dynamic string macros for C
|
utstring: dynamic string macros for C
|
||||||
=====================================
|
=====================================
|
||||||
Troy D. Hanson <tdh@tkhanson.net>
|
Troy D. Hanson <tdh@tkhanson.net>
|
||||||
v2.1.0, December 2018
|
v2.3.0, February 2021
|
||||||
|
|
||||||
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
|
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
|
||||||
|
|
||||||
|
|||||||
2
dependencies/uthash/package.json
vendored
2
dependencies/uthash/package.json
vendored
@@ -24,5 +24,5 @@
|
|||||||
"src/utstring.h"
|
"src/utstring.h"
|
||||||
],
|
],
|
||||||
|
|
||||||
"version": "2.1.0"
|
"version": "2.3.0"
|
||||||
}
|
}
|
||||||
|
|||||||
23
dependencies/uthash/src/utarray.h
vendored
23
dependencies/uthash/src/utarray.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
Copyright (c) 2008-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef UTARRAY_H
|
#ifndef UTARRAY_H
|
||||||
#define UTARRAY_H
|
#define UTARRAY_H
|
||||||
|
|
||||||
#define UTARRAY_VERSION 2.1.0
|
#define UTARRAY_VERSION 2.3.0
|
||||||
|
|
||||||
#include <stddef.h> /* size_t */
|
#include <stddef.h> /* size_t */
|
||||||
#include <string.h> /* memset, etc */
|
#include <string.h> /* memset, etc */
|
||||||
@@ -38,11 +38,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define UTARRAY_UNUSED
|
#define UTARRAY_UNUSED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef oom
|
|
||||||
#error "The name of macro 'oom' has been changed to 'utarray_oom'. Please update your code."
|
|
||||||
#define utarray_oom() oom()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef utarray_oom
|
#ifndef utarray_oom
|
||||||
#define utarray_oom() exit(-1)
|
#define utarray_oom() exit(-1)
|
||||||
#endif
|
#endif
|
||||||
@@ -232,8 +227,18 @@ typedef struct {
|
|||||||
|
|
||||||
/* last we pre-define a few icd for common utarrays of ints and strings */
|
/* last we pre-define a few icd for common utarrays of ints and strings */
|
||||||
static void utarray_str_cpy(void *dst, const void *src) {
|
static void utarray_str_cpy(void *dst, const void *src) {
|
||||||
char **_src = (char**)src, **_dst = (char**)dst;
|
char *const *srcc = (char *const *)src;
|
||||||
*_dst = (*_src == NULL) ? NULL : strdup(*_src);
|
char **dstc = (char**)dst;
|
||||||
|
if (*srcc == NULL) {
|
||||||
|
*dstc = NULL;
|
||||||
|
} else {
|
||||||
|
*dstc = (char*)malloc(strlen(*srcc) + 1);
|
||||||
|
if (*dstc == NULL) {
|
||||||
|
utarray_oom();
|
||||||
|
} else {
|
||||||
|
strcpy(*dstc, *srcc);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static void utarray_str_dtor(void *elt) {
|
static void utarray_str_dtor(void *elt) {
|
||||||
char **eltc = (char**)elt;
|
char **eltc = (char**)elt;
|
||||||
|
|||||||
78
dependencies/uthash/src/uthash.h
vendored
78
dependencies/uthash/src/uthash.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2003-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
Copyright (c) 2003-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -24,12 +24,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef UTHASH_H
|
#ifndef UTHASH_H
|
||||||
#define UTHASH_H
|
#define UTHASH_H
|
||||||
|
|
||||||
#define UTHASH_VERSION 2.1.0
|
#define UTHASH_VERSION 2.3.0
|
||||||
|
|
||||||
#include <string.h> /* memcmp, memset, strlen */
|
#include <string.h> /* memcmp, memset, strlen */
|
||||||
#include <stddef.h> /* ptrdiff_t */
|
#include <stddef.h> /* ptrdiff_t */
|
||||||
#include <stdlib.h> /* exit */
|
#include <stdlib.h> /* exit */
|
||||||
|
|
||||||
|
#if defined(HASH_DEFINE_OWN_STDINT) && HASH_DEFINE_OWN_STDINT
|
||||||
|
/* This codepath is provided for backward compatibility, but I plan to remove it. */
|
||||||
|
#warning "HASH_DEFINE_OWN_STDINT is deprecated; please use HASH_NO_STDINT instead"
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
#elif defined(HASH_NO_STDINT) && HASH_NO_STDINT
|
||||||
|
#else
|
||||||
|
#include <stdint.h> /* uint8_t, uint32_t */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* These macros use decltype or the earlier __typeof GNU extension.
|
/* These macros use decltype or the earlier __typeof GNU extension.
|
||||||
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
||||||
when compiling c++ source) this code uses whatever method is needed
|
when compiling c++ source) this code uses whatever method is needed
|
||||||
@@ -41,6 +51,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||||
#define NO_DECLTYPE
|
#define NO_DECLTYPE
|
||||||
#endif
|
#endif
|
||||||
|
#elif defined(__MCST__) /* Elbrus C Compiler */
|
||||||
|
#define DECLTYPE(x) (__typeof(x))
|
||||||
#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
|
#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
|
||||||
#define NO_DECLTYPE
|
#define NO_DECLTYPE
|
||||||
#else /* GNU, Sun and other compilers */
|
#else /* GNU, Sun and other compilers */
|
||||||
@@ -62,23 +74,6 @@ do {
|
|||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1600
|
|
||||||
#include <stdint.h>
|
|
||||||
#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__)
|
|
||||||
#include <stdint.h>
|
|
||||||
#else
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
#endif
|
|
||||||
#elif defined(__GNUC__) && !defined(__VXWORKS__)
|
|
||||||
#include <stdint.h>
|
|
||||||
#else
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef uthash_malloc
|
#ifndef uthash_malloc
|
||||||
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
|
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
|
||||||
#endif
|
#endif
|
||||||
@@ -92,15 +87,12 @@ typedef unsigned char uint8_t;
|
|||||||
#define uthash_strlen(s) strlen(s)
|
#define uthash_strlen(s) strlen(s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef uthash_memcmp
|
#ifndef HASH_FUNCTION
|
||||||
/* This warning will not catch programs that define uthash_memcmp AFTER including uthash.h. */
|
#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv)
|
||||||
#warning "uthash_memcmp is deprecated; please use HASH_KEYCMP instead"
|
|
||||||
#else
|
|
||||||
#define uthash_memcmp(a,b,n) memcmp(a,b,n)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HASH_KEYCMP
|
#ifndef HASH_KEYCMP
|
||||||
#define HASH_KEYCMP(a,b,n) uthash_memcmp(a,b,n)
|
#define HASH_KEYCMP(a,b,n) memcmp(a,b,n)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef uthash_noexpand_fyi
|
#ifndef uthash_noexpand_fyi
|
||||||
@@ -158,7 +150,7 @@ do {
|
|||||||
|
|
||||||
#define HASH_VALUE(keyptr,keylen,hashv) \
|
#define HASH_VALUE(keyptr,keylen,hashv) \
|
||||||
do { \
|
do { \
|
||||||
HASH_FCN(keyptr, keylen, hashv); \
|
HASH_FUNCTION(keyptr, keylen, hashv); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \
|
#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \
|
||||||
@@ -167,7 +159,7 @@ do {
|
|||||||
if (head) { \
|
if (head) { \
|
||||||
unsigned _hf_bkt; \
|
unsigned _hf_bkt; \
|
||||||
HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \
|
HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \
|
||||||
if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \
|
if (HASH_BLOOM_TEST((head)->hh.tbl, hashval)) { \
|
||||||
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \
|
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
@@ -204,7 +196,7 @@ do {
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))
|
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))
|
||||||
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))
|
#define HASH_BLOOM_BITTEST(bv,idx) ((bv[(idx)/8U] & (1U << ((idx)%8U))) != 0)
|
||||||
|
|
||||||
#define HASH_BLOOM_ADD(tbl,hashv) \
|
#define HASH_BLOOM_ADD(tbl,hashv) \
|
||||||
HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))
|
HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))
|
||||||
@@ -216,7 +208,7 @@ do {
|
|||||||
#define HASH_BLOOM_MAKE(tbl,oomed)
|
#define HASH_BLOOM_MAKE(tbl,oomed)
|
||||||
#define HASH_BLOOM_FREE(tbl)
|
#define HASH_BLOOM_FREE(tbl)
|
||||||
#define HASH_BLOOM_ADD(tbl,hashv)
|
#define HASH_BLOOM_ADD(tbl,hashv)
|
||||||
#define HASH_BLOOM_TEST(tbl,hashv) (1)
|
#define HASH_BLOOM_TEST(tbl,hashv) 1
|
||||||
#define HASH_BLOOM_BYTELEN 0U
|
#define HASH_BLOOM_BYTELEN 0U
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -408,7 +400,7 @@ do {
|
|||||||
do { \
|
do { \
|
||||||
IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \
|
IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \
|
||||||
(add)->hh.hashv = (hashval); \
|
(add)->hh.hashv = (hashval); \
|
||||||
(add)->hh.key = (char*) (keyptr); \
|
(add)->hh.key = (const void*) (keyptr); \
|
||||||
(add)->hh.keylen = (unsigned) (keylen_in); \
|
(add)->hh.keylen = (unsigned) (keylen_in); \
|
||||||
if (!(head)) { \
|
if (!(head)) { \
|
||||||
(add)->hh.next = NULL; \
|
(add)->hh.next = NULL; \
|
||||||
@@ -460,7 +452,7 @@ do {
|
|||||||
|
|
||||||
#define HASH_DELETE_HH(hh,head,delptrhh) \
|
#define HASH_DELETE_HH(hh,head,delptrhh) \
|
||||||
do { \
|
do { \
|
||||||
struct UT_hash_handle *_hd_hh_del = (delptrhh); \
|
const struct UT_hash_handle *_hd_hh_del = (delptrhh); \
|
||||||
if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \
|
if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \
|
||||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||||
uthash_free((head)->hh.tbl->buckets, \
|
uthash_free((head)->hh.tbl->buckets, \
|
||||||
@@ -590,13 +582,6 @@ do {
|
|||||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
|
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
|
|
||||||
#ifdef HASH_FUNCTION
|
|
||||||
#define HASH_FCN HASH_FUNCTION
|
|
||||||
#else
|
|
||||||
#define HASH_FCN HASH_JEN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
|
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
|
||||||
#define HASH_BER(key,keylen,hashv) \
|
#define HASH_BER(key,keylen,hashv) \
|
||||||
do { \
|
do { \
|
||||||
@@ -610,7 +595,9 @@ do {
|
|||||||
|
|
||||||
|
|
||||||
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
||||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
|
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
|
||||||
|
* (archive link: https://archive.is/Ivcan )
|
||||||
|
*/
|
||||||
#define HASH_SAX(key,keylen,hashv) \
|
#define HASH_SAX(key,keylen,hashv) \
|
||||||
do { \
|
do { \
|
||||||
unsigned _sx_i; \
|
unsigned _sx_i; \
|
||||||
@@ -695,7 +682,8 @@ do {
|
|||||||
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \
|
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \
|
||||||
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \
|
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \
|
||||||
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \
|
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \
|
||||||
case 1: _hj_i += _hj_key[0]; \
|
case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \
|
||||||
|
default: ; \
|
||||||
} \
|
} \
|
||||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@@ -743,6 +731,8 @@ do {
|
|||||||
case 1: hashv += *_sfh_key; \
|
case 1: hashv += *_sfh_key; \
|
||||||
hashv ^= hashv << 10; \
|
hashv ^= hashv << 10; \
|
||||||
hashv += hashv >> 1; \
|
hashv += hashv >> 1; \
|
||||||
|
break; \
|
||||||
|
default: ; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* Force "avalanching" of final 127 bits */ \
|
/* Force "avalanching" of final 127 bits */ \
|
||||||
@@ -764,7 +754,7 @@ do {
|
|||||||
} \
|
} \
|
||||||
while ((out) != NULL) { \
|
while ((out) != NULL) { \
|
||||||
if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \
|
if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \
|
||||||
if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \
|
if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
@@ -850,12 +840,12 @@ do {
|
|||||||
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
|
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
|
||||||
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
|
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
|
||||||
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
|
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||||
2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
|
sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \
|
||||||
if (!_he_new_buckets) { \
|
if (!_he_new_buckets) { \
|
||||||
HASH_RECORD_OOM(oomed); \
|
HASH_RECORD_OOM(oomed); \
|
||||||
} else { \
|
} else { \
|
||||||
uthash_bzero(_he_new_buckets, \
|
uthash_bzero(_he_new_buckets, \
|
||||||
2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
|
sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \
|
||||||
(tbl)->ideal_chain_maxlen = \
|
(tbl)->ideal_chain_maxlen = \
|
||||||
((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \
|
((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \
|
||||||
((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \
|
((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \
|
||||||
@@ -1142,7 +1132,7 @@ typedef struct UT_hash_handle {
|
|||||||
void *next; /* next element in app order */
|
void *next; /* next element in app order */
|
||||||
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
|
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
|
||||||
struct UT_hash_handle *hh_next; /* next hh in bucket order */
|
struct UT_hash_handle *hh_next; /* next hh in bucket order */
|
||||||
void *key; /* ptr to enclosing struct's key */
|
const void *key; /* ptr to enclosing struct's key */
|
||||||
unsigned keylen; /* enclosing struct's key len */
|
unsigned keylen; /* enclosing struct's key len */
|
||||||
unsigned hashv; /* result of hash-fcn(key) */
|
unsigned hashv; /* result of hash-fcn(key) */
|
||||||
} UT_hash_handle;
|
} UT_hash_handle;
|
||||||
|
|||||||
9
dependencies/uthash/src/utlist.h
vendored
9
dependencies/uthash/src/utlist.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2007-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
Copyright (c) 2007-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -24,7 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef UTLIST_H
|
#ifndef UTLIST_H
|
||||||
#define UTLIST_H
|
#define UTLIST_H
|
||||||
|
|
||||||
#define UTLIST_VERSION 2.1.0
|
#define UTLIST_VERSION 2.3.0
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@@ -70,6 +70,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||||
#define NO_DECLTYPE
|
#define NO_DECLTYPE
|
||||||
#endif
|
#endif
|
||||||
|
#elif defined(__MCST__) /* Elbrus C Compiler */
|
||||||
|
#define LDECLTYPE(x) __typeof(x)
|
||||||
#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
|
#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
|
||||||
#define NO_DECLTYPE
|
#define NO_DECLTYPE
|
||||||
#else /* GNU, Sun and other compilers */
|
#else /* GNU, Sun and other compilers */
|
||||||
@@ -709,7 +711,8 @@ do {
|
|||||||
assert((del)->prev != NULL); \
|
assert((del)->prev != NULL); \
|
||||||
if ((del)->prev == (del)) { \
|
if ((del)->prev == (del)) { \
|
||||||
(head)=NULL; \
|
(head)=NULL; \
|
||||||
} else if ((del)==(head)) { \
|
} else if ((del) == (head)) { \
|
||||||
|
assert((del)->next != NULL); \
|
||||||
(del)->next->prev = (del)->prev; \
|
(del)->next->prev = (del)->prev; \
|
||||||
(head) = (del)->next; \
|
(head) = (del)->next; \
|
||||||
} else { \
|
} else { \
|
||||||
|
|||||||
4
dependencies/uthash/src/utringbuffer.h
vendored
4
dependencies/uthash/src/utringbuffer.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2015-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
Copyright (c) 2015-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef UTRINGBUFFER_H
|
#ifndef UTRINGBUFFER_H
|
||||||
#define UTRINGBUFFER_H
|
#define UTRINGBUFFER_H
|
||||||
|
|
||||||
#define UTRINGBUFFER_VERSION 2.1.0
|
#define UTRINGBUFFER_VERSION 2.3.0
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
8
dependencies/uthash/src/utstack.h
vendored
8
dependencies/uthash/src/utstack.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2018-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
Copyright (c) 2018-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -24,7 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef UTSTACK_H
|
#ifndef UTSTACK_H
|
||||||
#define UTSTACK_H
|
#define UTSTACK_H
|
||||||
|
|
||||||
#define UTSTACK_VERSION 2.1.0
|
#define UTSTACK_VERSION 2.3.0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file contains macros to manipulate a singly-linked list as a stack.
|
* This file contains macros to manipulate a singly-linked list as a stack.
|
||||||
@@ -35,9 +35,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
* struct item {
|
* struct item {
|
||||||
* int id;
|
* int id;
|
||||||
* struct item *next;
|
* struct item *next;
|
||||||
* }
|
* };
|
||||||
*
|
*
|
||||||
* struct item *stack = NULL:
|
* struct item *stack = NULL;
|
||||||
*
|
*
|
||||||
* int main() {
|
* int main() {
|
||||||
* int count;
|
* int count;
|
||||||
|
|||||||
4
dependencies/uthash/src/utstring.h
vendored
4
dependencies/uthash/src/utstring.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
Copyright (c) 2008-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef UTSTRING_H
|
#ifndef UTSTRING_H
|
||||||
#define UTSTRING_H
|
#define UTSTRING_H
|
||||||
|
|
||||||
#define UTSTRING_VERSION 2.1.0
|
#define UTSTRING_VERSION 2.3.0
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
2
dependencies/uthash/tests/Makefile
vendored
2
dependencies/uthash/tests/Makefile
vendored
@@ -12,7 +12,7 @@ PROGS = test1 test2 test3 test4 test5 test6 test7 test8 test9 \
|
|||||||
test66 test67 test68 test69 test70 test71 test72 test73 \
|
test66 test67 test68 test69 test70 test71 test72 test73 \
|
||||||
test74 test75 test76 test77 test78 test79 test80 test81 \
|
test74 test75 test76 test77 test78 test79 test80 test81 \
|
||||||
test82 test83 test84 test85 test86 test87 test88 test89 \
|
test82 test83 test84 test85 test86 test87 test88 test89 \
|
||||||
test90 test91 test92 test93 test94 test95
|
test90 test91 test92 test93 test94 test95 test96 test97
|
||||||
CFLAGS += -I$(HASHDIR)
|
CFLAGS += -I$(HASHDIR)
|
||||||
#CFLAGS += -DHASH_BLOOM=16
|
#CFLAGS += -DHASH_BLOOM=16
|
||||||
#CFLAGS += -O2
|
#CFLAGS += -O2
|
||||||
|
|||||||
10
dependencies/uthash/tests/README
vendored
10
dependencies/uthash/tests/README
vendored
@@ -7,7 +7,7 @@ test2: make 10-item hash, lookup items with even keys, print
|
|||||||
test3: make 10-item hash, delete items with even keys, print others
|
test3: make 10-item hash, delete items with even keys, print others
|
||||||
test4: 10 structs have dual hash handles, separate keys
|
test4: 10 structs have dual hash handles, separate keys
|
||||||
test5: 10 structs have dual hash handles, lookup evens by alt key
|
test5: 10 structs have dual hash handles, lookup evens by alt key
|
||||||
test6: test alt malloc macros (and alt memcmp macro)
|
test6: test alt malloc macros (and alt key-comparison macro)
|
||||||
test7: test alt malloc macros with 1000 structs so bucket expansion occurs
|
test7: test alt malloc macros with 1000 structs so bucket expansion occurs
|
||||||
test8: test num_items counter in UT_hash_handle
|
test8: test num_items counter in UT_hash_handle
|
||||||
test9: test "find" after bucket expansion
|
test9: test "find" after bucket expansion
|
||||||
@@ -89,10 +89,16 @@ test84: test HASH_REPLACE_STR with char* key
|
|||||||
test85: test HASH_OVERHEAD on null and non null hash
|
test85: test HASH_OVERHEAD on null and non null hash
|
||||||
test86: test *_APPEND_ELEM / *_PREPEND_ELEM (Thilo Schulz)
|
test86: test *_APPEND_ELEM / *_PREPEND_ELEM (Thilo Schulz)
|
||||||
test87: test HASH_ADD_INORDER() macro (Thilo Schulz)
|
test87: test HASH_ADD_INORDER() macro (Thilo Schulz)
|
||||||
test88: test alt memcmp and strlen macros
|
test88: test alt key-comparison and strlen macros
|
||||||
test89: test code from the tinydtls project
|
test89: test code from the tinydtls project
|
||||||
test90: regression-test HASH_ADD_KEYPTR_INORDER (IronBug)
|
test90: regression-test HASH_ADD_KEYPTR_INORDER (IronBug)
|
||||||
test91: test LL_INSERT_INORDER etc.
|
test91: test LL_INSERT_INORDER etc.
|
||||||
|
test92: HASH_NONFATAL_OOM
|
||||||
|
test93: alt_fatal
|
||||||
|
test94: utlist with fields named other than 'next' and 'prev'
|
||||||
|
test95: utstack
|
||||||
|
test96: HASH_FUNCTION + HASH_KEYCMP
|
||||||
|
test97: deleting a const-qualified node from a hash
|
||||||
|
|
||||||
Other Make targets
|
Other Make targets
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|||||||
86
dependencies/uthash/tests/example.c
vendored
86
dependencies/uthash/tests/example.c
vendored
@@ -1,25 +1,25 @@
|
|||||||
#include <stdio.h> /* gets */
|
#include <stdio.h> /* printf */
|
||||||
#include <stdlib.h> /* atoi, malloc */
|
#include <stdlib.h> /* atoi, malloc */
|
||||||
#include <string.h> /* strcpy */
|
#include <string.h> /* strcpy */
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
|
||||||
struct my_struct {
|
struct my_struct {
|
||||||
int id; /* key */
|
int id; /* key */
|
||||||
char name[10];
|
char name[21];
|
||||||
UT_hash_handle hh; /* makes this structure hashable */
|
UT_hash_handle hh; /* makes this structure hashable */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct my_struct *users = NULL;
|
struct my_struct *users = NULL;
|
||||||
|
|
||||||
void add_user(int user_id, char *name)
|
void add_user(int user_id, const char *name)
|
||||||
{
|
{
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */
|
HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */
|
||||||
if (s==NULL) {
|
if (s == NULL) {
|
||||||
s = (struct my_struct*)malloc(sizeof(struct my_struct));
|
s = (struct my_struct*)malloc(sizeof *s);
|
||||||
s->id = user_id;
|
s->id = user_id;
|
||||||
HASH_ADD_INT( users, id, s ); /* id: name of key field */
|
HASH_ADD_INT(users, id, s); /* id is the key field */
|
||||||
}
|
}
|
||||||
strcpy(s->name, name);
|
strcpy(s->name, name);
|
||||||
}
|
}
|
||||||
@@ -28,23 +28,24 @@ struct my_struct *find_user(int user_id)
|
|||||||
{
|
{
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */
|
HASH_FIND_INT(users, &user_id, s); /* s: output pointer */
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_user(struct my_struct *user)
|
void delete_user(struct my_struct *user)
|
||||||
{
|
{
|
||||||
HASH_DEL( users, user); /* user: pointer to deletee */
|
HASH_DEL(users, user); /* user: pointer to deletee */
|
||||||
free(user);
|
free(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_all()
|
void delete_all()
|
||||||
{
|
{
|
||||||
struct my_struct *current_user, *tmp;
|
struct my_struct *current_user;
|
||||||
|
struct my_struct *tmp;
|
||||||
|
|
||||||
HASH_ITER(hh, users, current_user, tmp) {
|
HASH_ITER(hh, users, current_user, tmp) {
|
||||||
HASH_DEL(users,current_user); /* delete it (users advances to next) */
|
HASH_DEL(users, current_user); /* delete it (users advances to next) */
|
||||||
free(current_user); /* free it */
|
free(current_user); /* free it */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,41 +53,45 @@ void print_users()
|
|||||||
{
|
{
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
|
|
||||||
for(s=users; s != NULL; s=(struct my_struct*)(s->hh.next)) {
|
for (s = users; s != NULL; s = (struct my_struct*)(s->hh.next)) {
|
||||||
printf("user id %d: name %s\n", s->id, s->name);
|
printf("user id %d: name %s\n", s->id, s->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int name_sort(struct my_struct *a, struct my_struct *b)
|
int by_name(const struct my_struct *a, const struct my_struct *b)
|
||||||
{
|
{
|
||||||
return strcmp(a->name,b->name);
|
return strcmp(a->name, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int id_sort(struct my_struct *a, struct my_struct *b)
|
int by_id(const struct my_struct *a, const struct my_struct *b)
|
||||||
{
|
{
|
||||||
return (a->id - b->id);
|
return (a->id - b->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort_by_name()
|
const char *getl(const char *prompt)
|
||||||
{
|
{
|
||||||
HASH_SORT(users, name_sort);
|
static char buf[21];
|
||||||
}
|
char *p;
|
||||||
|
printf("%s? ", prompt); fflush(stdout);
|
||||||
void sort_by_id()
|
p = fgets(buf, sizeof(buf), stdin);
|
||||||
{
|
if (p == NULL || (p = strchr(buf, '\n')) == NULL) {
|
||||||
HASH_SORT(users, id_sort);
|
puts("Invalid input!");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
char in[10];
|
int id = 1;
|
||||||
int id=1, running=1;
|
int running = 1;
|
||||||
struct my_struct *s;
|
struct my_struct *s;
|
||||||
unsigned num_users;
|
int temp;
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
printf(" 1. add user\n");
|
printf(" 1. add user\n");
|
||||||
printf(" 2. add/rename user by id\n");
|
printf(" 2. add or rename user by id\n");
|
||||||
printf(" 3. find user\n");
|
printf(" 3. find user\n");
|
||||||
printf(" 4. delete user\n");
|
printf(" 4. delete user\n");
|
||||||
printf(" 5. delete all users\n");
|
printf(" 5. delete all users\n");
|
||||||
@@ -95,27 +100,20 @@ int main()
|
|||||||
printf(" 8. print users\n");
|
printf(" 8. print users\n");
|
||||||
printf(" 9. count users\n");
|
printf(" 9. count users\n");
|
||||||
printf("10. quit\n");
|
printf("10. quit\n");
|
||||||
gets(in);
|
switch (atoi(getl("Command"))) {
|
||||||
switch(atoi(in)) {
|
|
||||||
case 1:
|
case 1:
|
||||||
printf("name?\n");
|
add_user(id++, getl("Name (20 char max)"));
|
||||||
add_user(id++, gets(in));
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
printf("id?\n");
|
temp = atoi(getl("ID"));
|
||||||
gets(in);
|
add_user(temp, getl("Name (20 char max)"));
|
||||||
id = atoi(in);
|
|
||||||
printf("name?\n");
|
|
||||||
add_user(id, gets(in));
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
printf("id?\n");
|
s = find_user(atoi(getl("ID to find")));
|
||||||
s = find_user(atoi(gets(in)));
|
|
||||||
printf("user: %s\n", s ? s->name : "unknown");
|
printf("user: %s\n", s ? s->name : "unknown");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
printf("id?\n");
|
s = find_user(atoi(getl("ID to delete")));
|
||||||
s = find_user(atoi(gets(in)));
|
|
||||||
if (s) {
|
if (s) {
|
||||||
delete_user(s);
|
delete_user(s);
|
||||||
} else {
|
} else {
|
||||||
@@ -126,20 +124,20 @@ int main()
|
|||||||
delete_all();
|
delete_all();
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
sort_by_name();
|
HASH_SORT(users, by_name);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
sort_by_id();
|
HASH_SORT(users, by_id);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
print_users();
|
print_users();
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
num_users=HASH_COUNT(users);
|
temp = HASH_COUNT(users);
|
||||||
printf("there are %u users\n", num_users);
|
printf("there are %d users\n", temp);
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
running=0;
|
running = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
dependencies/uthash/tests/hashscan.c
vendored
2
dependencies/uthash/tests/hashscan.c
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2005-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
|
Copyright (c) 2005-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
4
dependencies/uthash/tests/keystats
vendored
4
dependencies/uthash/tests/keystats
vendored
@@ -12,9 +12,11 @@ sub usage {
|
|||||||
|
|
||||||
usage if ((@ARGV == 0) or ($ARGV[0] eq '-h'));
|
usage if ((@ARGV == 0) or ($ARGV[0] eq '-h'));
|
||||||
|
|
||||||
my @exes = glob "$FindBin::Bin/keystat.???";
|
my @exes = glob "'$FindBin::Bin/keystat.???'";
|
||||||
|
|
||||||
my %stats;
|
my %stats;
|
||||||
for my $exe (@exes) {
|
for my $exe (@exes) {
|
||||||
|
$exe =~ s/\ /\\ /g;
|
||||||
$stats{$exe} = `$exe @ARGV`;
|
$stats{$exe} = `$exe @ARGV`;
|
||||||
delete $stats{$exe} if ($? != 0); # omit hash functions that fail to produce stats (nx)
|
delete $stats{$exe} if ($? != 0); # omit hash functions that fail to produce stats (nx)
|
||||||
}
|
}
|
||||||
|
|||||||
3
dependencies/uthash/tests/test10.c
vendored
3
dependencies/uthash/tests/test10.c
vendored
@@ -47,5 +47,8 @@ int main()
|
|||||||
HASH_FIND(alth,altusers,&i,sizeof(int),tmp);
|
HASH_FIND(alth,altusers,&i,sizeof(int),tmp);
|
||||||
printf("%d %s in alth\n", i, (tmp != NULL) ? "found" : "not found");
|
printf("%d %s in alth\n", i, (tmp != NULL) ? "found" : "not found");
|
||||||
|
|
||||||
|
HASH_CLEAR(hh, users);
|
||||||
|
HASH_CLEAR(alth, altusers);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
1
dependencies/uthash/tests/test57.ans
vendored
1
dependencies/uthash/tests/test57.ans
vendored
@@ -1 +0,0 @@
|
|||||||
found
|
|
||||||
|
|||||||
57
dependencies/uthash/tests/test57.c
vendored
57
dependencies/uthash/tests/test57.c
vendored
@@ -1,5 +1,5 @@
|
|||||||
#include <stdio.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stddef.h>
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -8,25 +8,46 @@ typedef struct {
|
|||||||
UT_hash_handle hh;
|
UT_hash_handle hh;
|
||||||
} el_t;
|
} el_t;
|
||||||
|
|
||||||
|
el_t *findit(el_t *hash, void *keytofind)
|
||||||
|
{
|
||||||
|
el_t *found;
|
||||||
|
HASH_FIND_PTR(hash, &keytofind, found);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
el_t *d;
|
|
||||||
el_t *hash = NULL;
|
el_t *hash = NULL;
|
||||||
char *someaddr = NULL;
|
el_t e1;
|
||||||
el_t *e = (el_t*)malloc(sizeof(el_t));
|
el_t e2;
|
||||||
if (!e) {
|
|
||||||
return -1;
|
e1.key = NULL;
|
||||||
}
|
e1.i = 1;
|
||||||
e->key = (void*)someaddr;
|
|
||||||
e->i = 1;
|
e2.key = &e2;
|
||||||
HASH_ADD_PTR(hash,key,e);
|
e2.i = 2;
|
||||||
HASH_FIND_PTR(hash, &someaddr, d);
|
|
||||||
if (d != NULL) {
|
assert(findit(hash, NULL) == NULL);
|
||||||
printf("found\n");
|
assert(findit(hash, &e1) == NULL);
|
||||||
}
|
assert(findit(hash, &e2) == NULL);
|
||||||
|
|
||||||
|
HASH_ADD_PTR(hash, key, &e1);
|
||||||
|
assert(findit(hash, NULL) == &e1);
|
||||||
|
assert(findit(hash, &e1) == NULL);
|
||||||
|
assert(findit(hash, &e2) == NULL);
|
||||||
|
|
||||||
|
HASH_ADD_PTR(hash, key, &e2);
|
||||||
|
assert(findit(hash, NULL) == &e1);
|
||||||
|
assert(findit(hash, &e1) == NULL);
|
||||||
|
assert(findit(hash, &e2) == &e2);
|
||||||
|
|
||||||
|
HASH_DEL(hash, &e1);
|
||||||
|
assert(findit(hash, NULL) == NULL);
|
||||||
|
assert(findit(hash, &e1) == NULL);
|
||||||
|
assert(findit(hash, &e2) == &e2);
|
||||||
|
|
||||||
|
HASH_CLEAR(hh, hash);
|
||||||
|
assert(hash == NULL);
|
||||||
|
|
||||||
/* release memory */
|
|
||||||
HASH_DEL(hash,e);
|
|
||||||
free(e);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
13
dependencies/uthash/tests/test6.c
vendored
13
dependencies/uthash/tests/test6.c
vendored
@@ -7,15 +7,16 @@
|
|||||||
/* Set up macros for alternative malloc/free functions */
|
/* Set up macros for alternative malloc/free functions */
|
||||||
#undef uthash_malloc
|
#undef uthash_malloc
|
||||||
#undef uthash_free
|
#undef uthash_free
|
||||||
#undef uthash_memcmp
|
|
||||||
#undef uthash_strlen
|
#undef uthash_strlen
|
||||||
#undef uthash_bzero
|
#undef uthash_bzero
|
||||||
#define uthash_malloc(sz) alt_malloc(sz)
|
#define uthash_malloc(sz) alt_malloc(sz)
|
||||||
#define uthash_free(ptr,sz) alt_free(ptr,sz)
|
#define uthash_free(ptr,sz) alt_free(ptr,sz)
|
||||||
#define uthash_memcmp(a,b,n) alt_memcmp(a,b,n)
|
|
||||||
#define uthash_strlen(s) ..fail_to_compile..
|
#define uthash_strlen(s) ..fail_to_compile..
|
||||||
#define uthash_bzero(a,n) alt_bzero(a,n)
|
#define uthash_bzero(a,n) alt_bzero(a,n)
|
||||||
|
|
||||||
|
#undef HASH_KEYCMP
|
||||||
|
#define HASH_KEYCMP(a,b,n) alt_keycmp(a,b,n)
|
||||||
|
|
||||||
typedef struct example_user_t {
|
typedef struct example_user_t {
|
||||||
int id;
|
int id;
|
||||||
int cookie;
|
int cookie;
|
||||||
@@ -41,10 +42,10 @@ static void alt_free(void *ptr, size_t sz)
|
|||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alt_memcmp_count = 0;
|
static int alt_keycmp_count = 0;
|
||||||
static int alt_memcmp(const void *a, const void *b, size_t n)
|
static int alt_keycmp(const void *a, const void *b, size_t n)
|
||||||
{
|
{
|
||||||
++alt_memcmp_count;
|
++alt_keycmp_count;
|
||||||
return memcmp(a,b,n);
|
return memcmp(a,b,n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +116,7 @@ int main()
|
|||||||
#else
|
#else
|
||||||
assert(alt_bzero_count == 2);
|
assert(alt_bzero_count == 2);
|
||||||
#endif
|
#endif
|
||||||
assert(alt_memcmp_count == 10);
|
assert(alt_keycmp_count == 10);
|
||||||
assert(alt_malloc_balance == 0);
|
assert(alt_malloc_balance == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
2
dependencies/uthash/tests/test65.c
vendored
2
dependencies/uthash/tests/test65.c
vendored
@@ -3,7 +3,7 @@
|
|||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
|
||||||
// this is an example of how to do a LRU cache in C using uthash
|
// this is an example of how to do a LRU cache in C using uthash
|
||||||
// http://troydhanson.github.com/uthash/
|
// https://troydhanson.github.io/uthash/
|
||||||
// by Jehiah Czebotar 2011 - jehiah@gmail.com
|
// by Jehiah Czebotar 2011 - jehiah@gmail.com
|
||||||
// this code is in the public domain http://unlicense.org/
|
// this code is in the public domain http://unlicense.org/
|
||||||
|
|
||||||
|
|||||||
7
dependencies/uthash/tests/test76.c
vendored
7
dependencies/uthash/tests/test76.c
vendored
@@ -8,8 +8,8 @@ int main()
|
|||||||
char V_NeedleStr[] = "needle\0s";
|
char V_NeedleStr[] = "needle\0s";
|
||||||
long *V_KMP_Table;
|
long *V_KMP_Table;
|
||||||
long V_FindPos;
|
long V_FindPos;
|
||||||
size_t V_StartPos;
|
size_t V_StartPos = 0;
|
||||||
size_t V_FindCnt;
|
size_t V_FindCnt = 0;
|
||||||
|
|
||||||
|
|
||||||
utstring_new(s);
|
utstring_new(s);
|
||||||
@@ -24,9 +24,6 @@ int main()
|
|||||||
if (V_KMP_Table != NULL) {
|
if (V_KMP_Table != NULL) {
|
||||||
_utstring_BuildTable(utstring_body(t), utstring_len(t), V_KMP_Table);
|
_utstring_BuildTable(utstring_body(t), utstring_len(t), V_KMP_Table);
|
||||||
|
|
||||||
V_FindCnt = 0;
|
|
||||||
V_FindPos = 0;
|
|
||||||
V_StartPos = 0;
|
|
||||||
do {
|
do {
|
||||||
V_FindPos = _utstring_find(utstring_body(s) + V_StartPos,
|
V_FindPos = _utstring_find(utstring_body(s) + V_StartPos,
|
||||||
utstring_len(s) - V_StartPos,
|
utstring_len(s) - V_StartPos,
|
||||||
|
|||||||
4
dependencies/uthash/tests/test77.c
vendored
4
dependencies/uthash/tests/test77.c
vendored
@@ -9,7 +9,7 @@ int main()
|
|||||||
long *V_KMP_Table;
|
long *V_KMP_Table;
|
||||||
long V_FindPos;
|
long V_FindPos;
|
||||||
size_t V_StartPos;
|
size_t V_StartPos;
|
||||||
size_t V_FindCnt;
|
size_t V_FindCnt = 0;
|
||||||
|
|
||||||
|
|
||||||
utstring_new(s);
|
utstring_new(s);
|
||||||
@@ -24,8 +24,6 @@ int main()
|
|||||||
if (V_KMP_Table != NULL) {
|
if (V_KMP_Table != NULL) {
|
||||||
_utstring_BuildTableR(utstring_body(t), utstring_len(t), V_KMP_Table);
|
_utstring_BuildTableR(utstring_body(t), utstring_len(t), V_KMP_Table);
|
||||||
|
|
||||||
V_FindCnt = 0;
|
|
||||||
V_FindPos = 0;
|
|
||||||
V_StartPos = utstring_len(s) - 1;
|
V_StartPos = utstring_len(s) - 1;
|
||||||
do {
|
do {
|
||||||
V_FindPos = _utstring_findR(utstring_body(s),
|
V_FindPos = _utstring_findR(utstring_body(s),
|
||||||
|
|||||||
20
dependencies/uthash/tests/test88.ans
vendored
20
dependencies/uthash/tests/test88.ans
vendored
@@ -9,22 +9,22 @@ alt_strlen
|
|||||||
alt_strlen
|
alt_strlen
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_memcmp
|
alt_keycmp
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_memcmp
|
alt_keycmp
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_memcmp
|
alt_keycmp
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_memcmp
|
alt_keycmp
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_memcmp
|
alt_keycmp
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_memcmp
|
alt_keycmp
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_memcmp
|
alt_keycmp
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_memcmp
|
alt_keycmp
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_memcmp
|
alt_keycmp
|
||||||
alt_strlen
|
alt_strlen
|
||||||
alt_memcmp
|
alt_keycmp
|
||||||
|
|||||||
8
dependencies/uthash/tests/test88.c
vendored
8
dependencies/uthash/tests/test88.c
vendored
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
/* This is mostly a copy of test6.c. */
|
/* This is mostly a copy of test6.c. */
|
||||||
|
|
||||||
#undef uthash_memcmp
|
#undef HASH_KEYCMP
|
||||||
#undef uthash_strlen
|
#undef uthash_strlen
|
||||||
#define uthash_memcmp(a,b,n) alt_memcmp(a,b,n)
|
#define HASH_KEYCMP(a,b,n) alt_keycmp(a,b,n)
|
||||||
#define uthash_strlen(s) alt_strlen(s)
|
#define uthash_strlen(s) alt_strlen(s)
|
||||||
|
|
||||||
typedef struct example_user_t {
|
typedef struct example_user_t {
|
||||||
@@ -19,9 +19,9 @@ typedef struct example_user_t {
|
|||||||
UT_hash_handle hh;
|
UT_hash_handle hh;
|
||||||
} example_user_t;
|
} example_user_t;
|
||||||
|
|
||||||
static int alt_memcmp(const void *a, const void *b, size_t n)
|
static int alt_keycmp(const void *a, const void *b, size_t n)
|
||||||
{
|
{
|
||||||
puts("alt_memcmp");
|
puts("alt_keycmp");
|
||||||
return memcmp(a,b,n);
|
return memcmp(a,b,n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
dependencies/uthash/tests/test93.c
vendored
37
dependencies/uthash/tests/test93.c
vendored
@@ -39,43 +39,39 @@ static void alt_fatal(char const * s) {
|
|||||||
longjmp(j_buf, 1);
|
longjmp(j_buf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static example_user_t * init_user(int need_malloc_cnt) {
|
static void init_users(int need_malloc_cnt) {
|
||||||
users = 0;
|
users = NULL;
|
||||||
example_user_t * user = (example_user_t*)malloc(sizeof(example_user_t));
|
example_user_t * user = (example_user_t*)malloc(sizeof(example_user_t));
|
||||||
user->id = user_id;
|
user->id = user_id;
|
||||||
is_fatal = 0;
|
is_fatal = 0;
|
||||||
malloc_cnt = need_malloc_cnt;
|
malloc_cnt = need_malloc_cnt;
|
||||||
/* printf("adding to hash...\n"); */
|
|
||||||
if (!setjmp(j_buf)) {
|
if (!setjmp(j_buf)) {
|
||||||
HASH_ADD_INT(users, id, user);
|
HASH_ADD_INT(users, id, user);
|
||||||
|
} else {
|
||||||
|
free(user);
|
||||||
}
|
}
|
||||||
return user;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
example_user_t *user;
|
||||||
|
|
||||||
#define init(a) do { \
|
init_users(3); /* bloom filter must fail */
|
||||||
} while(0)
|
|
||||||
|
|
||||||
example_user_t * user;
|
|
||||||
|
|
||||||
user = init_user(3); /* bloom filter must fail */
|
|
||||||
if (!is_fatal) {
|
if (!is_fatal) {
|
||||||
printf("fatal not called after bloom failure\n");
|
printf("fatal not called after bloom failure\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
user = init_user(2); /* bucket creation must fail */
|
init_users(2); /* bucket creation must fail */
|
||||||
if (!is_fatal) {
|
if (!is_fatal) {
|
||||||
printf("fatal not called after bucket creation failure\n");
|
printf("fatal not called after bucket creation failure\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
user = init_user(1); /* table creation must fail */
|
init_users(1); /* table creation must fail */
|
||||||
if (!is_fatal) {
|
if (!is_fatal) {
|
||||||
printf("fatal not called after table creation failure\n");
|
printf("fatal not called after table creation failure\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
user = init_user(4); /* hash must create OK */
|
init_users(4); /* hash must create OK */
|
||||||
if (is_fatal) {
|
if (is_fatal) {
|
||||||
printf("fatal error when creating hash normally\n");
|
printf("fatal error when creating hash normally\n");
|
||||||
/* bad idea to continue running */
|
/* bad idea to continue running */
|
||||||
@@ -83,19 +79,20 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* let's add users until expansion fails */
|
/* let's add users until expansion fails */
|
||||||
users = 0;
|
users = NULL;
|
||||||
malloc_cnt = 4;
|
malloc_cnt = 4;
|
||||||
while (1) {
|
while (1) {
|
||||||
user = (example_user_t*)malloc(sizeof(example_user_t));
|
|
||||||
user->id = user_id;
|
|
||||||
if (user_id++ == 1000) {
|
if (user_id++ == 1000) {
|
||||||
printf("there is no way 1000 iterations didn't require realloc\n");
|
printf("there is no way 1000 iterations didn't require realloc\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
user = (example_user_t*)malloc(sizeof(example_user_t));
|
||||||
|
user->id = user_id;
|
||||||
if (!setjmp(j_buf)) {
|
if (!setjmp(j_buf)) {
|
||||||
HASH_ADD_INT(users, id, user);
|
HASH_ADD_INT(users, id, user);
|
||||||
|
} else {
|
||||||
|
free(user);
|
||||||
}
|
}
|
||||||
malloc_cnt = 0;
|
|
||||||
if (malloc_failed) {
|
if (malloc_failed) {
|
||||||
|
|
||||||
if (!is_fatal) {
|
if (!is_fatal) {
|
||||||
@@ -108,12 +105,12 @@ int main()
|
|||||||
/* we can't really do anything, the hash is not in consistent
|
/* we can't really do anything, the hash is not in consistent
|
||||||
* state, so assume this is a success. */
|
* state, so assume this is a success. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
malloc_cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HASH_CLEAR(hh, users);
|
||||||
|
|
||||||
printf("End\n");
|
printf("End\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
40
dependencies/uthash/tests/test96.ans
vendored
Normal file
40
dependencies/uthash/tests/test96.ans
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
time 56 not found, inserting it
|
||||||
|
time 7 not found, inserting it
|
||||||
|
time 10 not found, inserting it
|
||||||
|
time 39 not found, inserting it
|
||||||
|
time 82 found with value 10
|
||||||
|
time 15 found with value 39
|
||||||
|
time 31 found with value 7
|
||||||
|
time 26 not found, inserting it
|
||||||
|
time 51 found with value 39
|
||||||
|
time 83 not found, inserting it
|
||||||
|
time 46 found with value 10
|
||||||
|
time 92 found with value 56
|
||||||
|
time 49 not found, inserting it
|
||||||
|
time 25 found with value 49
|
||||||
|
time 80 found with value 56
|
||||||
|
time 54 not found, inserting it
|
||||||
|
time 97 found with value 49
|
||||||
|
time 9 not found, inserting it
|
||||||
|
time 34 found with value 10
|
||||||
|
time 86 found with value 26
|
||||||
|
time 87 found with value 39
|
||||||
|
time 28 not found, inserting it
|
||||||
|
time 13 found with value 49
|
||||||
|
time 91 found with value 7
|
||||||
|
time 95 found with value 83
|
||||||
|
time 63 found with value 39
|
||||||
|
time 71 found with value 83
|
||||||
|
time 100 found with value 28
|
||||||
|
time 44 found with value 56
|
||||||
|
time 42 found with value 54
|
||||||
|
time 16 found with value 28
|
||||||
|
time 32 found with value 56
|
||||||
|
time 6 found with value 54
|
||||||
|
time 85 found with value 49
|
||||||
|
time 40 found with value 28
|
||||||
|
time 20 found with value 56
|
||||||
|
time 18 found with value 54
|
||||||
|
time 99 found with value 39
|
||||||
|
time 22 found with value 10
|
||||||
|
time 1 found with value 49
|
||||||
48
dependencies/uthash/tests/test96.c
vendored
Normal file
48
dependencies/uthash/tests/test96.c
vendored
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define HASH_FUNCTION(a,n,hv) (hv = clockface_hash(*(const int*)(a)))
|
||||||
|
#define HASH_KEYCMP(a,b,n) clockface_neq(*(const int*)(a), *(const int*)(b))
|
||||||
|
|
||||||
|
#include "uthash.h"
|
||||||
|
|
||||||
|
struct clockface {
|
||||||
|
int time;
|
||||||
|
UT_hash_handle hh;
|
||||||
|
};
|
||||||
|
|
||||||
|
int clockface_hash(int time)
|
||||||
|
{
|
||||||
|
return (time % 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
int clockface_neq(int t1, int t2)
|
||||||
|
{
|
||||||
|
return ((t1 % 12) != (t2 % 12));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int random_data[] = {
|
||||||
|
56, 7, 10, 39, 82, 15, 31, 26, 51, 83,
|
||||||
|
46, 92, 49, 25, 80, 54, 97, 9, 34, 86,
|
||||||
|
87, 28, 13, 91, 95, 63, 71, 100, 44, 42,
|
||||||
|
16, 32, 6, 85, 40, 20, 18, 99, 22, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clockface *times = NULL;
|
||||||
|
for (int i=0; i < 40; ++i) {
|
||||||
|
struct clockface *elt = (struct clockface *)malloc(sizeof(*elt));
|
||||||
|
struct clockface *found = NULL;
|
||||||
|
elt->time = random_data[i];
|
||||||
|
HASH_FIND_INT(times, &elt->time, found);
|
||||||
|
if (found) {
|
||||||
|
printf("time %d found with value %d\n", elt->time, found->time);
|
||||||
|
} else {
|
||||||
|
printf("time %d not found, inserting it\n", elt->time);
|
||||||
|
HASH_ADD_INT(times, time, elt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
57
dependencies/uthash/tests/test97.c
vendored
Normal file
57
dependencies/uthash/tests/test97.c
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "uthash.h"
|
||||||
|
|
||||||
|
struct item {
|
||||||
|
int payload;
|
||||||
|
UT_hash_handle hh;
|
||||||
|
};
|
||||||
|
|
||||||
|
void delete_without_modifying(struct item *head, const struct item *p)
|
||||||
|
{
|
||||||
|
struct item old;
|
||||||
|
memcpy(&old, p, sizeof(struct item)); // also copy the padding bits
|
||||||
|
assert(memcmp(&old, p, sizeof(struct item)) == 0);
|
||||||
|
assert(p->hh.tbl == head->hh.tbl); // class invariant
|
||||||
|
HASH_DEL(head, p);
|
||||||
|
assert(memcmp(&old, p, sizeof(struct item)) == 0); // unmodified by HASH_DEL
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
struct item *items = NULL;
|
||||||
|
struct item *found = NULL;
|
||||||
|
int fortytwo = 42;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i < 100; i++) {
|
||||||
|
struct item *p = (struct item *)malloc(sizeof *p);
|
||||||
|
p->payload = i;
|
||||||
|
HASH_ADD_INT(items, payload, p);
|
||||||
|
}
|
||||||
|
assert(HASH_COUNT(items) == 100);
|
||||||
|
|
||||||
|
// Delete item "42" from the hash, wherever it is.
|
||||||
|
HASH_FIND_INT(items, &fortytwo, found);
|
||||||
|
assert(found != NULL);
|
||||||
|
assert(found->payload == 42);
|
||||||
|
delete_without_modifying(items, found);
|
||||||
|
|
||||||
|
assert(HASH_COUNT(items) == 99);
|
||||||
|
HASH_FIND_INT(items, &fortytwo, found);
|
||||||
|
assert(found == NULL);
|
||||||
|
|
||||||
|
// Delete the very first item in the hash.
|
||||||
|
assert(items != NULL);
|
||||||
|
i = items->payload;
|
||||||
|
delete_without_modifying(items, items);
|
||||||
|
|
||||||
|
assert(HASH_COUNT(items) == 98);
|
||||||
|
HASH_FIND_INT(items, &i, found);
|
||||||
|
assert(found == NULL);
|
||||||
|
|
||||||
|
// leak the items, we don't care
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -3,51 +3,96 @@
|
|||||||
Some ready-2-use/ready-2-extend examples/utils.
|
Some ready-2-use/ready-2-extend examples/utils.
|
||||||
All examples are prefixed with their used LANG.
|
All examples are prefixed with their used LANG.
|
||||||
|
|
||||||
|
## c-analysed
|
||||||
|
|
||||||
|
A feature extractor useful for ML/DL use cases.
|
||||||
|
It generates CSV files from flow "analyse" events.
|
||||||
|
Used also by `tests/run_tests.sh` if available.
|
||||||
|
|
||||||
## c-captured
|
## c-captured
|
||||||
|
|
||||||
A capture daemon suitable for low-resource devices.
|
A capture daemon suitable for low-resource devices.
|
||||||
It saves flows that were guessed/undetected/risky/midstream to a PCAP file for manual analysis.
|
It saves flows that were guessed/undetected/risky/midstream to a PCAP file for manual analysis.
|
||||||
Basicially a combination of `py-flow-undetected-to-pcap` and `py-risky-flow-to-pcap`.
|
Used also by `tests/run_tests.sh` if available.
|
||||||
|
|
||||||
## c-collectd
|
## c-collectd
|
||||||
|
|
||||||
A collecd-exec compatible middleware that gathers statistic values from nDPId.
|
A collecd-exec compatible middleware that gathers statistic values from nDPId.
|
||||||
|
Used also by `tests/run_tests.sh` if available.
|
||||||
|
|
||||||
## c-json-stdout
|
## c-influxd
|
||||||
|
|
||||||
Tiny nDPId json dumper. Does not provide any useful funcationality besides dumping parsed JSON objects.
|
An InfluxDB push daemon. It aggregates various statistics gathered from nDPId.
|
||||||
|
The results are sent to a specified InfluxDB endpoint.
|
||||||
|
|
||||||
## go-dashboard
|

|
||||||
|
|
||||||
A discontinued tty UI nDPId dashboard. I've figured out that Go + UI is a bad idea, in particular if performance is a concern.
|
## c-notifyd
|
||||||
|
|
||||||
|
A notification daemon that sends information about suspicious flow events to DBUS.
|
||||||
|
|
||||||
|
## c-simple
|
||||||
|
|
||||||
|
Integration example that verifies flow timeouts on SIGUSR1.
|
||||||
|
|
||||||
|
## cxx-graph
|
||||||
|
|
||||||
|
A standalone GLFW/OpenGL application that draws statistical data using ImWeb/ImPlot/ImGui.
|
||||||
|
|
||||||
|
## js-rt-analyzer
|
||||||
|
|
||||||
|
[nDPId-rt-analyzer](https://gitlab.com/verzulli/ndpid-rt-analyzer.git)
|
||||||
|
|
||||||
|
## js-rt-analyzer-frontend
|
||||||
|
|
||||||
|
[nDPId-rt-analyzer-frontend](https://gitlab.com/verzulli/ndpid-rt-analyzer-frontend.git)
|
||||||
|
|
||||||
## py-flow-info
|
## py-flow-info
|
||||||
|
|
||||||
Prints prettyfied information about flow events.
|
Console friendly, colorful, prettyfied event printer.
|
||||||
|
Required by `tests/run_tests.sh`
|
||||||
|
|
||||||
## py-flow-undetected-to-pcap
|
## py-machine-learning
|
||||||
|
|
||||||
Captures and saves undetected flows to a PCAP file.
|
Contains:
|
||||||
|
|
||||||
|
1. Classification via Random Forests and SciLearn
|
||||||
|
2. Anomaly Detection via Autoencoder and Keras (Work-In-Progress!)
|
||||||
|
|
||||||
|
Use sklearn together with CSVs created with **c-analysed** to train and predict DPI detections.
|
||||||
|
|
||||||
|
Try it with: `./examples/py-machine-learning/sklearn_random_forest.py --csv ./ndpi-analysed.csv --proto-class tls.youtube --proto-class tls.github --proto-class tls.spotify --proto-class tls.facebook --proto-class tls.instagram --proto-class tls.doh_dot --proto-class quic --proto-class icmp`
|
||||||
|
|
||||||
|
This way you should get 9 different classification classes.
|
||||||
|
You may notice that some classes e.g. TLS protocol classifications have a higher false-negative/false-positive rate.
|
||||||
|
Unfortunately, I can not provide any datasets due to some privacy concerns.
|
||||||
|
|
||||||
|
But you may use a [pre-trained model](https://drive.google.com/file/d/1KEwbP-Gx7KJr54wNoa63I56VI4USCAPL/view?usp=sharing) with `--load-model`.
|
||||||
|
|
||||||
|
## py-flow-multiprocess
|
||||||
|
|
||||||
|
Simple Python Multiprocess example spawning two worker processes, one connecting to nDPIsrvd and one printing flow id's to STDOUT.
|
||||||
|
|
||||||
## py-json-stdout
|
## py-json-stdout
|
||||||
|
|
||||||
Dump received and parsed JSON strings.
|
Dump received and parsed JSON objects.
|
||||||
|
|
||||||
## py-risky-flow-to-pcap
|
|
||||||
|
|
||||||
Captures and saves risky flows to a PCAP file.
|
|
||||||
|
|
||||||
## py-schema-validation
|
## py-schema-validation
|
||||||
|
|
||||||
Validate nDPId JSON strings against pre-defined JSON schema's.
|
Validate nDPId JSON messages against pre-defined JSON schema's.
|
||||||
See `schema/`.
|
See `schema/`.
|
||||||
Required by `tests/run_tests.sh`
|
Required by `tests/run_tests.sh`
|
||||||
|
|
||||||
## py-semantic-validation
|
## py-semantic-validation
|
||||||
|
|
||||||
Validate nDPId JSON strings against internal event semantics.
|
Validate nDPId JSON messages against internal event semantics.
|
||||||
Required by `tests/run_tests.sh`
|
Required by `tests/run_tests.sh`
|
||||||
|
|
||||||
## py-ja3-checker
|
## rs-simple
|
||||||
|
|
||||||
Captures JA3 hashes from nDPIsrvd and checks them against known hashes from [ja3er.com](https://ja3er.com).
|
A straight forward Rust deserialization/parsing example.
|
||||||
|
|
||||||
|
## yaml-filebeat
|
||||||
|
An example filebeat configuration to parse and send nDPId JSON
|
||||||
|
messages to Elasticsearch. Allowing long term storage and data visualization with kibana
|
||||||
|
and various other tools that interact with Elasticsearch (No logstash required).
|
||||||
|
|||||||
2320
examples/c-analysed/c-analysed.c
Normal file
2320
examples/c-analysed/c-analysed.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
14
examples/c-collectd/README.md
Normal file
14
examples/c-collectd/README.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
HowTo use this
|
||||||
|
==============
|
||||||
|
|
||||||
|
This HowTo assumes that the examples were sucessfully compiled and installed within the prefix `/usr` on your target machine.
|
||||||
|
|
||||||
|
1. Make sure nDPId and Collectd is running.
|
||||||
|
2. Edit `collectd.conf` usually in `/etc`.
|
||||||
|
3. Add the lines in `plugin_nDPIsrvd.conf` to your `collectd.conf`.
|
||||||
|
You may adapt this file depending what command line arguments you'd supplied to `nDPId`.
|
||||||
|
4. Reload your Collectd instance.
|
||||||
|
5. Optional: Install a http server of your choice.
|
||||||
|
Place the files in `/usr/share/nDPId/nDPIsrvd-collectd/www` somewhere in your www root.
|
||||||
|
6. Optional: Add `rrdgraph.sh` as cron job e.g. `0 * * * * /usr/share/nDPId/nDPIsrvd-collectd/rrdgraph.sh [path-to-the-collectd-rrd-directory] [path-to-your-dpi-wwwroot]`.
|
||||||
|
This will run `rrdgraph.sh` once per hour. You can adjust this until it fit your needs.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -3,12 +3,12 @@ LoadPlugin exec
|
|||||||
<Plugin exec>
|
<Plugin exec>
|
||||||
Exec "ndpi" "/usr/bin/nDPIsrvd-collectd"
|
Exec "ndpi" "/usr/bin/nDPIsrvd-collectd"
|
||||||
# Exec "ndpi" "/usr/bin/nDPIsrvd-collectd" "-s" "/tmp/ndpid-distributor.sock"
|
# Exec "ndpi" "/usr/bin/nDPIsrvd-collectd" "-s" "/tmp/ndpid-distributor.sock"
|
||||||
# Exec "ndpi" "/usr/bin/nDPIsrvd-collectd" "-s" "127.0.0.1:7000"
|
# Exec "ndpi" "/tmp/nDPIsrvd-collectd" "-s" "127.0.0.1:7000"
|
||||||
</Plugin>
|
</Plugin>
|
||||||
|
|
||||||
# Uncomment for testing
|
# Uncomment for testing
|
||||||
LoadPlugin write_log
|
#LoadPlugin write_log
|
||||||
LoadPlugin rrdtool
|
#LoadPlugin rrdtool
|
||||||
<Plugin rrdtool>
|
#<Plugin rrdtool>
|
||||||
DataDir "nDPIsrvd-collectd"
|
# DataDir "nDPIsrvd-collectd"
|
||||||
</Plugin>
|
#</Plugin>
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
# Add those types to collectd types.db
|
|
||||||
# e.g. `cat plugin_nDPIsrvd_types.db >>/usr/share/collectd/types.db'
|
|
||||||
|
|
||||||
# flow event counters
|
|
||||||
flow_new_count value:GAUGE:0:U
|
|
||||||
flow_end_count value:GAUGE:0:U
|
|
||||||
flow_idle_count value:GAUGE:0:U
|
|
||||||
flow_guessed_count value:GAUGE:0:U
|
|
||||||
flow_detected_count value:GAUGE:0:U
|
|
||||||
flow_detection_update_count value:GAUGE:0:U
|
|
||||||
flow_not_detected_count value:GAUGE:0:U
|
|
||||||
|
|
||||||
# flow additional counters
|
|
||||||
flow_packet_count value:GAUGE:0:U
|
|
||||||
flow_total_bytes value:GAUGE:0:U
|
|
||||||
flow_risky_count value:GAUGE:0:U
|
|
||||||
|
|
||||||
# flow breed counters
|
|
||||||
flow_breed_safe_count value:GAUGE:0:U
|
|
||||||
flow_breed_acceptable_count value:GAUGE:0:U
|
|
||||||
flow_breed_fun_count value:GAUGE:0:U
|
|
||||||
flow_breed_unsafe_count value:GAUGE:0:U
|
|
||||||
flow_breed_potentially_dangerous_count value:GAUGE:0:U
|
|
||||||
flow_breed_dangerous_count value:GAUGE:0:U
|
|
||||||
flow_breed_unrated_count value:GAUGE:0:U
|
|
||||||
flow_breed_unknown_count value:GAUGE:0:U
|
|
||||||
|
|
||||||
# flow category counters
|
|
||||||
flow_category_media_count value:GAUGE:0:U
|
|
||||||
flow_category_vpn_count value:GAUGE:0:U
|
|
||||||
flow_category_email_count value:GAUGE:0:U
|
|
||||||
flow_category_data_transfer_count value:GAUGE:0:U
|
|
||||||
flow_category_web_count value:GAUGE:0:U
|
|
||||||
flow_category_social_network_count value:GAUGE:0:U
|
|
||||||
flow_category_download_count value:GAUGE:0:U
|
|
||||||
flow_category_game_count value:GAUGE:0:U
|
|
||||||
flow_category_chat_count value:GAUGE:0:U
|
|
||||||
flow_category_voip_count value:GAUGE:0:U
|
|
||||||
flow_category_database_count value:GAUGE:0:U
|
|
||||||
flow_category_remote_access_count value:GAUGE:0:U
|
|
||||||
flow_category_cloud_count value:GAUGE:0:U
|
|
||||||
flow_category_network_count value:GAUGE:0:U
|
|
||||||
flow_category_collaborative_count value:GAUGE:0:U
|
|
||||||
flow_category_rpc_count value:GAUGE:0:U
|
|
||||||
flow_category_streaming_count value:GAUGE:0:U
|
|
||||||
flow_category_system_count value:GAUGE:0:U
|
|
||||||
flow_category_software_update_count value:GAUGE:0:U
|
|
||||||
flow_category_music_count value:GAUGE:0:U
|
|
||||||
flow_category_video_count value:GAUGE:0:U
|
|
||||||
flow_category_shopping_count value:GAUGE:0:U
|
|
||||||
flow_category_productivity_count value:GAUGE:0:U
|
|
||||||
flow_category_file_sharing_count value:GAUGE:0:U
|
|
||||||
flow_category_mining_count value:GAUGE:0:U
|
|
||||||
flow_category_malware_count value:GAUGE:0:U
|
|
||||||
flow_category_advertisment_count value:GAUGE:0:U
|
|
||||||
flow_category_other_count value:GAUGE:0:U
|
|
||||||
flow_category_unknown_count value:GAUGE:0:U
|
|
||||||
|
|
||||||
# flow l3 / l4 counters
|
|
||||||
flow_l3_ip4_count value:GAUGE:0:U
|
|
||||||
flow_l3_ip6_count value:GAUGE:0:U
|
|
||||||
flow_l3_other_count value:GAUGE:0:U
|
|
||||||
flow_l4_tcp_count value:GAUGE:0:U
|
|
||||||
flow_l4_udp_count value:GAUGE:0:U
|
|
||||||
flow_l4_other_count value:GAUGE:0:U
|
|
||||||
631
examples/c-collectd/rrdgraph.sh
Executable file
631
examples/c-collectd/rrdgraph.sh
Executable file
@@ -0,0 +1,631 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
RRDDIR="${1}"
|
||||||
|
OUTDIR="${2}"
|
||||||
|
RRDARGS="--width=800 --height=400"
|
||||||
|
REQUIRED_RRDCNT=130
|
||||||
|
|
||||||
|
if [ -z "${RRDDIR}" ]; then
|
||||||
|
printf '%s: Missing RRD directory which contains nDPIsrvd/Collectd files.\n' "${0}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${OUTDIR}" ]; then
|
||||||
|
printf '%s: Missing Output directory which contains HTML files.\n' "${0}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $(ls -al ${RRDDIR}/gauge-flow_*.rrd | wc -l) -ne ${REQUIRED_RRDCNT} ]; then
|
||||||
|
printf '%s: Missing some *.rrd files. Expected: %s, Got: %s\n' "${0}" "${REQUIRED_RRDCNT}" "$(ls -al ${RRDDIR}/gauge-flow_*.rrd | wc -l)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -r "${OUTDIR}/index.html" -o ! -r "${OUTDIR}/flows.html" -o ! -r "${OUTDIR}/other.html" -o ! -r "${OUTDIR}/detections.html" -o ! -r "${OUTDIR}/categories.html" ]; then
|
||||||
|
printf '%s: Missing some *.html files.\n' "${0}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TIME_PAST_HOUR="--start=-3600 --end=-0"
|
||||||
|
TIME_PAST_12HOURS="--start=-43200 --end=-0"
|
||||||
|
TIME_PAST_DAY="--start=-86400 --end=-0"
|
||||||
|
TIME_PAST_WEEK="--start=-604800 --end=-0"
|
||||||
|
TIME_PAST_MONTH="--start=-2419200 --end=-0"
|
||||||
|
TIME_PAST_3MONTHS="--start=-8035200 --end=-0"
|
||||||
|
TIME_PAST_YEAR="--start=-31536000 --end=-0"
|
||||||
|
|
||||||
|
rrdtool_graph_colorize_missing_data() {
|
||||||
|
printf 'CDEF:offline=%s,UN,INF,* AREA:offline#B3B3B311:' "${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
rrdtool_graph_print_cur_min_max_avg() {
|
||||||
|
printf 'GPRINT:%s:LAST:Current\:%%8.2lf ' "${1}"
|
||||||
|
printf 'GPRINT:%s:MIN:Minimum\:%%8.2lf ' "${1}"
|
||||||
|
printf 'GPRINT:%s:MAX:Maximum\:%%8.2lf ' "${1}"
|
||||||
|
printf 'GPRINT:%s:AVERAGE:Average\:%%8.2lf\\n' "${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
rrdtool_graph() {
|
||||||
|
TITLE="${1}"
|
||||||
|
shift
|
||||||
|
YAXIS_NAME="${1}"
|
||||||
|
shift
|
||||||
|
OUTPNG="${1}"
|
||||||
|
shift
|
||||||
|
|
||||||
|
rrdtool graph ${RRDARGS} -t "${TITLE} (past hour)" -v ${YAXIS_NAME} -Y ${TIME_PAST_HOUR} "${OUTPNG}_past_hour.png" ${*}
|
||||||
|
rrdtool graph ${RRDARGS} -t "${TITLE} (past 12 hours)" -v ${YAXIS_NAME} -Y ${TIME_PAST_12HOURS} "${OUTPNG}_past_12hours.png" ${*}
|
||||||
|
rrdtool graph ${RRDARGS} -t "${TITLE} (past day)" -v ${YAXIS_NAME} -Y ${TIME_PAST_DAY} "${OUTPNG}_past_day.png" ${*}
|
||||||
|
rrdtool graph ${RRDARGS} -t "${TITLE} (past week)" -v ${YAXIS_NAME} -Y ${TIME_PAST_WEEK} "${OUTPNG}_past_week.png" ${*}
|
||||||
|
rrdtool graph ${RRDARGS} -t "${TITLE} (past month)" -v ${YAXIS_NAME} -Y ${TIME_PAST_MONTH} "${OUTPNG}_past_month.png" ${*}
|
||||||
|
rrdtool graph ${RRDARGS} -t "${TITLE} (past 3 months)" -v ${YAXIS_NAME} -Y ${TIME_PAST_3MONTHS} "${OUTPNG}_past_month.png" ${*}
|
||||||
|
rrdtool graph ${RRDARGS} -t "${TITLE} (past year)" -v ${YAXIS_NAME} -Y ${TIME_PAST_YEAR} "${OUTPNG}_past_year.png" ${*}
|
||||||
|
}
|
||||||
|
|
||||||
|
rrdtool_graph Flows Amount "${OUTDIR}/flows" \
|
||||||
|
DEF:flows_active=${RRDDIR}/gauge-flow_active_count.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data flows_active) \
|
||||||
|
AREA:flows_active#54EC48::STACK \
|
||||||
|
LINE2:flows_active#24BC14:"Active" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg flows_active)
|
||||||
|
rrdtool_graph Detections Amount "${OUTDIR}/detections" \
|
||||||
|
DEF:flows_detected=${RRDDIR}/gauge-flow_detected_count.rrd:value:AVERAGE \
|
||||||
|
DEF:flows_guessed=${RRDDIR}/gauge-flow_guessed_count.rrd:value:AVERAGE \
|
||||||
|
DEF:flows_not_detected=${RRDDIR}/gauge-flow_not_detected_count.rrd:value:AVERAGE \
|
||||||
|
DEF:flows_detection_update=${RRDDIR}/counter-flow_detection_update_count.rrd:value:AVERAGE \
|
||||||
|
DEF:flows_risky=${RRDDIR}/counter-flow_risky_count.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data flows_detected) \
|
||||||
|
AREA:flows_detected#00bfff::STACK \
|
||||||
|
AREA:flows_detection_update#a1b8c4::STACK \
|
||||||
|
AREA:flows_guessed#ffff4d::STACK \
|
||||||
|
AREA:flows_not_detected#ffa64d::STACK \
|
||||||
|
AREA:flows_risky#ff4000::STACK \
|
||||||
|
LINE2:flows_detected#0000ff:"Detected........" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg flows_detected) \
|
||||||
|
LINE2:flows_guessed#cccc00:"Guessed........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg flows_guessed) \
|
||||||
|
LINE2:flows_not_detected#ff8000:"Not-Detected...." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg flows_not_detected) \
|
||||||
|
LINE2:flows_detection_update#4f6e7d:"Detection-Update" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg flows_detection_update) \
|
||||||
|
LINE2:flows_risky#b32d00:"Risky..........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg flows_risky)
|
||||||
|
rrdtool_graph "Traffic (IN/OUT)" Bytes "${OUTDIR}/traffic" \
|
||||||
|
DEF:total_src_bytes=${RRDDIR}/counter-flow_src_total_bytes.rrd:value:AVERAGE \
|
||||||
|
DEF:total_dst_bytes=${RRDDIR}/counter-flow_dst_total_bytes.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data total_src_bytes) \
|
||||||
|
AREA:total_src_bytes#00cc99:"Total-Bytes-Source2Dest":STACK \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg total_src_bytes) \
|
||||||
|
STACK:total_dst_bytes#669999:"Total-Bytes-Dest2Source" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg total_dst_bytes)
|
||||||
|
rrdtool_graph Layer3-Flows Amount "${OUTDIR}/layer3" \
|
||||||
|
DEF:layer3_ip4=${RRDDIR}/gauge-flow_l3_ip4_count.rrd:value:AVERAGE \
|
||||||
|
DEF:layer3_ip6=${RRDDIR}/gauge-flow_l3_ip6_count.rrd:value:AVERAGE \
|
||||||
|
DEF:layer3_other=${RRDDIR}/gauge-flow_l3_other_count.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data layer3_ip4) \
|
||||||
|
AREA:layer3_ip4#73d97d::STACK \
|
||||||
|
AREA:layer3_ip6#66b3ff::STACK \
|
||||||
|
AREA:layer3_other#bea1c4::STACK \
|
||||||
|
LINE2:layer3_ip4#21772a:"IPv4." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg layer3_ip4) \
|
||||||
|
LINE2:layer3_ip6#0066cc:"IPv6." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg layer3_ip6) \
|
||||||
|
LINE2:layer3_other#92629d:"Other" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg layer3_other)
|
||||||
|
rrdtool_graph Layer4-Flows Amount "${OUTDIR}/layer4" \
|
||||||
|
DEF:layer4_tcp=${RRDDIR}/gauge-flow_l4_tcp_count.rrd:value:AVERAGE \
|
||||||
|
DEF:layer4_udp=${RRDDIR}/gauge-flow_l4_udp_count.rrd:value:AVERAGE \
|
||||||
|
DEF:layer4_icmp=${RRDDIR}/gauge-flow_l4_icmp_count.rrd:value:AVERAGE \
|
||||||
|
DEF:layer4_other=${RRDDIR}/gauge-flow_l4_other_count.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data layer4_tcp) \
|
||||||
|
AREA:layer4_tcp#73d97d::STACK \
|
||||||
|
AREA:layer4_udp#66b3ff::STACK \
|
||||||
|
AREA:layer4_icmp#ee5d9a::STACK \
|
||||||
|
AREA:layer4_other#bea1c4::STACK \
|
||||||
|
LINE2:layer4_tcp#21772a:"TCP.." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg layer4_tcp) \
|
||||||
|
LINE2:layer4_udp#0066cc:"UDP.." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg layer4_udp) \
|
||||||
|
LINE2:layer4_icmp#d01663:"ICMP." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg layer4_icmp) \
|
||||||
|
LINE2:layer4_other#83588d:"Other" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg layer4_other)
|
||||||
|
rrdtool_graph Confidence Amount "${OUTDIR}/confidence" \
|
||||||
|
DEF:conf_ip=${RRDDIR}/gauge-flow_confidence_by_ip.rrd:value:AVERAGE \
|
||||||
|
DEF:conf_port=${RRDDIR}/gauge-flow_confidence_by_port.rrd:value:AVERAGE \
|
||||||
|
DEF:conf_aggr=${RRDDIR}/gauge-flow_confidence_dpi_aggressive.rrd:value:AVERAGE \
|
||||||
|
DEF:conf_cache=${RRDDIR}/gauge-flow_confidence_dpi_cache.rrd:value:AVERAGE \
|
||||||
|
DEF:conf_pcache=${RRDDIR}/gauge-flow_confidence_dpi_partial_cache.rrd:value:AVERAGE \
|
||||||
|
DEF:conf_part=${RRDDIR}/gauge-flow_confidence_dpi_partial.rrd:value:AVERAGE \
|
||||||
|
DEF:conf_dpi=${RRDDIR}/gauge-flow_confidence_dpi.rrd:value:AVERAGE \
|
||||||
|
DEF:conf_nbpf=${RRDDIR}/gauge-flow_confidence_nbpf.rrd:value:AVERAGE \
|
||||||
|
DEF:conf_ukn=${RRDDIR}/gauge-flow_confidence_unknown.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data conf_ip) \
|
||||||
|
AREA:conf_ip#4dff4d::STACK \
|
||||||
|
AREA:conf_port#c2ff33::STACK \
|
||||||
|
AREA:conf_aggr#ffe433::STACK \
|
||||||
|
AREA:conf_cache#ffb133::STACK \
|
||||||
|
AREA:conf_pcache#ff5f33::STACK \
|
||||||
|
AREA:conf_part#e74b5b::STACK \
|
||||||
|
AREA:conf_dpi#a5aca0::STACK \
|
||||||
|
AREA:conf_nbpf#d7c1cc::STACK \
|
||||||
|
AREA:conf_ukn#ddccbb::STACK \
|
||||||
|
LINE2:conf_ip#00e600:"By-IP................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg conf_ip) \
|
||||||
|
LINE2:conf_port#8fce00:"By-Port.............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg conf_port) \
|
||||||
|
LINE2:conf_aggr#e6c700:"DPI-Aggressive......." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg conf_aggr) \
|
||||||
|
LINE2:conf_cache#e68e00:"DPI-Cache............" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg conf_cache) \
|
||||||
|
LINE2:conf_pcache#e63200:"DPI-Partial-Cache...." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg conf_pcache) \
|
||||||
|
LINE2:conf_part#c61b2b:"DPI-Partial.........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg conf_part) \
|
||||||
|
LINE2:conf_dpi#7e8877:"DPI.................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg conf_dpi) \
|
||||||
|
LINE2:conf_nbpf#ae849a:"nBPF................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg conf_nbpf) \
|
||||||
|
LINE2:conf_ukn#aa9988:"Unknown.............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg conf_ukn)
|
||||||
|
rrdtool_graph Breeds Amount "${OUTDIR}/breed" \
|
||||||
|
DEF:breed_safe=${RRDDIR}/gauge-flow_breed_safe_count.rrd:value:AVERAGE \
|
||||||
|
DEF:breed_acceptable=${RRDDIR}/gauge-flow_breed_acceptable_count.rrd:value:AVERAGE \
|
||||||
|
DEF:breed_fun=${RRDDIR}/gauge-flow_breed_fun_count.rrd:value:AVERAGE \
|
||||||
|
DEF:breed_unsafe=${RRDDIR}/gauge-flow_breed_unsafe_count.rrd:value:AVERAGE \
|
||||||
|
DEF:breed_potentially_dangerous=${RRDDIR}/gauge-flow_breed_potentially_dangerous_count.rrd:value:AVERAGE \
|
||||||
|
DEF:breed_dangerous=${RRDDIR}/gauge-flow_breed_dangerous_count.rrd:value:AVERAGE \
|
||||||
|
DEF:breed_unrated=${RRDDIR}/gauge-flow_breed_unrated_count.rrd:value:AVERAGE \
|
||||||
|
DEF:breed_unknown=${RRDDIR}/gauge-flow_breed_unknown_count.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data breed_safe) \
|
||||||
|
AREA:breed_safe#4dff4d::STACK \
|
||||||
|
AREA:breed_acceptable#c2ff33::STACK \
|
||||||
|
AREA:breed_fun#ffe433::STACK \
|
||||||
|
AREA:breed_unsafe#ffb133::STACK \
|
||||||
|
AREA:breed_potentially_dangerous#ff5f33::STACK \
|
||||||
|
AREA:breed_dangerous#e74b5b::STACK \
|
||||||
|
AREA:breed_unrated#a5aca0::STACK \
|
||||||
|
AREA:breed_unknown#d7c1cc::STACK \
|
||||||
|
LINE2:breed_safe#00e600:"Safe................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg breed_safe) \
|
||||||
|
LINE2:breed_acceptable#8fce00:"Acceptable..........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg breed_acceptable) \
|
||||||
|
LINE2:breed_fun#e6c700:"Fun.................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg breed_fun) \
|
||||||
|
LINE2:breed_unsafe#e68e00:"Unsafe..............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg breed_unsafe) \
|
||||||
|
LINE2:breed_potentially_dangerous#e63200:"Potentially-Dangerous" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg breed_potentially_dangerous) \
|
||||||
|
LINE2:breed_dangerous#c61b2b:"Dangerous............" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg breed_dangerous) \
|
||||||
|
LINE2:breed_unrated#7e8877:"Unrated.............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg breed_unrated) \
|
||||||
|
LINE2:breed_unknown#ae849a:"Unknown.............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg breed_unknown)
|
||||||
|
rrdtool_graph Categories 'Amount(SUM)' "${OUTDIR}/categories" \
|
||||||
|
DEF:cat_adlt=${RRDDIR}/gauge-flow_category_adult_content_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_ads=${RRDDIR}/gauge-flow_category_advertisment_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_chat=${RRDDIR}/gauge-flow_category_chat_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_cloud=${RRDDIR}/gauge-flow_category_cloud_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_collab=${RRDDIR}/gauge-flow_category_collaborative_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_conn=${RRDDIR}/gauge-flow_category_conn_check_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_cybr=${RRDDIR}/gauge-flow_category_cybersecurity_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_xfer=${RRDDIR}/gauge-flow_category_data_transfer_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_db=${RRDDIR}/gauge-flow_category_database_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_dl=${RRDDIR}/gauge-flow_category_download_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_mail=${RRDDIR}/gauge-flow_category_email_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_fs=${RRDDIR}/gauge-flow_category_file_sharing_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_game=${RRDDIR}/gauge-flow_category_game_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_gamb=${RRDDIR}/gauge-flow_category_gambling_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_iot=${RRDDIR}/gauge-flow_category_iot_scada_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_mal=${RRDDIR}/gauge-flow_category_malware_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_med=${RRDDIR}/gauge-flow_category_media_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_min=${RRDDIR}/gauge-flow_category_mining_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_mus=${RRDDIR}/gauge-flow_category_music_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_net=${RRDDIR}/gauge-flow_category_network_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_prod=${RRDDIR}/gauge-flow_category_productivity_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_rem=${RRDDIR}/gauge-flow_category_remote_access_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_rpc=${RRDDIR}/gauge-flow_category_rpc_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_shop=${RRDDIR}/gauge-flow_category_shopping_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_soc=${RRDDIR}/gauge-flow_category_social_network_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_soft=${RRDDIR}/gauge-flow_category_software_update_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_str=${RRDDIR}/gauge-flow_category_streaming_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_sys=${RRDDIR}/gauge-flow_category_system_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_ukn=${RRDDIR}/gauge-flow_category_unknown_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_uns=${RRDDIR}/gauge-flow_category_unspecified_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_vid=${RRDDIR}/gauge-flow_category_video_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_vrt=${RRDDIR}/gauge-flow_category_virt_assistant_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_voip=${RRDDIR}/gauge-flow_category_voip_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_vpn=${RRDDIR}/gauge-flow_category_vpn_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_web=${RRDDIR}/gauge-flow_category_web_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_banned=${RRDDIR}/gauge-flow_category_banned_site_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_unavail=${RRDDIR}/gauge-flow_category_site_unavail_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_allowed=${RRDDIR}/gauge-flow_category_allowed_site_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_antimal=${RRDDIR}/gauge-flow_category_antimalware_count.rrd:value:AVERAGE \
|
||||||
|
DEF:cat_crypto=${RRDDIR}/gauge-flow_category_crypto_currency_count.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data cat_adlt) \
|
||||||
|
AREA:cat_adlt#f0c032:"Adult.................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_adlt) \
|
||||||
|
STACK:cat_ads#f1c232:"Advertisment..........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_ads) \
|
||||||
|
STACK:cat_chat#6fa8dc:"Chat..................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_chat) \
|
||||||
|
STACK:cat_cloud#2986cc:"Cloud.................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_cloud) \
|
||||||
|
STACK:cat_collab#3212aa:"Collaborative.........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_collab) \
|
||||||
|
STACK:cat_conn#22aa11:"Connection-Check......." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_conn) \
|
||||||
|
STACK:cat_cybr#00ff00:"Cybersecurity.........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_cybr) \
|
||||||
|
STACK:cat_xfer#16537e:"Data-Transfer.........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_xfer) \
|
||||||
|
STACK:cat_db#cc0000:"Database..............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_db) \
|
||||||
|
STACK:cat_dl#6a329f:"Download..............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_dl) \
|
||||||
|
STACK:cat_mail#3600cc:"Mail..................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_mail) \
|
||||||
|
STACK:cat_fs#c90076:"File-Sharing..........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_fs) \
|
||||||
|
STACK:cat_game#00ff26:"Game..................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_game) \
|
||||||
|
STACK:cat_gamb#aa0026:"Gambling..............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_gamb) \
|
||||||
|
STACK:cat_iot#227867:"IoT-Scada.............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_iot) \
|
||||||
|
STACK:cat_mal#f44336:"Malware................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_mal) \
|
||||||
|
STACK:cat_med#ff8300:"Media.................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_med) \
|
||||||
|
STACK:cat_min#ff0000:"Mining................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_min) \
|
||||||
|
STACK:cat_mus#00fff0:"Music.................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_mus) \
|
||||||
|
STACK:cat_net#ddff00:"Network................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_net) \
|
||||||
|
STACK:cat_prod#29ff00:"Productivity..........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_prod) \
|
||||||
|
STACK:cat_rem#b52c2c:"Remote-Access.........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_rem) \
|
||||||
|
STACK:cat_rpc#e15a5a:"Remote-Procedure-Call.." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_rpc) \
|
||||||
|
STACK:cat_shop#0065ff:"Shopping..............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_shop) \
|
||||||
|
STACK:cat_soc#8fce00:"Social-Network........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_soc) \
|
||||||
|
STACK:cat_soft#007a0d:"Software-Update........" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_soft) \
|
||||||
|
STACK:cat_str#ff00b8:"Streaming.............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_str) \
|
||||||
|
STACK:cat_sys#f4ff00:"System................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_sys) \
|
||||||
|
STACK:cat_ukn#999999:"Unknown................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_ukn) \
|
||||||
|
STACK:cat_uns#999999:"Unspecified............" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_uns) \
|
||||||
|
STACK:cat_vid#518820:"Video.................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_vid) \
|
||||||
|
STACK:cat_vrt#216820:"Virtual-Assistant......" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_vrt) \
|
||||||
|
STACK:cat_voip#ffc700:"Voice-Over-IP.........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_voip) \
|
||||||
|
STACK:cat_vpn#378035:"Virtual-Private-Network" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_vpn) \
|
||||||
|
STACK:cat_web#00fffb:"Web...................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_web) \
|
||||||
|
STACK:cat_banned#ff1010:"Banned-Sites..........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_banned) \
|
||||||
|
STACK:cat_unavail#ff1010:"Sites-Unavailable......" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_unavail) \
|
||||||
|
STACK:cat_allowed#ff1010:"Allowed-Sites.........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_allowed) \
|
||||||
|
STACK:cat_antimal#ff1010:"Antimalware............" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_antimal) \
|
||||||
|
STACK:cat_crypto#afaf00:"Crypto-Currency........" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg cat_crypto)
|
||||||
|
rrdtool_graph JSON 'Lines' "${OUTDIR}/json_lines" \
|
||||||
|
DEF:json_lines=${RRDDIR}/counter-json_lines.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data json_lines) \
|
||||||
|
AREA:json_lines#4dff4d::STACK \
|
||||||
|
LINE2:json_lines#00e600:"JSON-lines" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg json_lines)
|
||||||
|
rrdtool_graph JSON 'Bytes' "${OUTDIR}/json_bytes" \
|
||||||
|
DEF:json_bytes=${RRDDIR}/counter-json_bytes.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data json_bytes) \
|
||||||
|
AREA:json_bytes#4dff4d::STACK \
|
||||||
|
LINE2:json_bytes#00e600:"JSON-bytes" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg json_bytes)
|
||||||
|
rrdtool_graph Events 'Amount' "${OUTDIR}/events" \
|
||||||
|
DEF:init=${RRDDIR}/counter-init_count.rrd:value:AVERAGE \
|
||||||
|
DEF:reconnect=${RRDDIR}/counter-reconnect_count.rrd:value:AVERAGE \
|
||||||
|
DEF:shutdown=${RRDDIR}/counter-shutdown_count.rrd:value:AVERAGE \
|
||||||
|
DEF:status=${RRDDIR}/counter-status_count.rrd:value:AVERAGE \
|
||||||
|
DEF:packet=${RRDDIR}/counter-packet_count.rrd:value:AVERAGE \
|
||||||
|
DEF:packet_flow=${RRDDIR}/counter-packet_flow_count.rrd:value:AVERAGE \
|
||||||
|
DEF:new=${RRDDIR}/counter-flow_new_count.rrd:value:AVERAGE \
|
||||||
|
DEF:ewd=${RRDDIR}/counter-flow_end_count.rrd:value:AVERAGE \
|
||||||
|
DEF:idle=${RRDDIR}/counter-flow_idle_count.rrd:value:AVERAGE \
|
||||||
|
DEF:update=${RRDDIR}/counter-flow_update_count.rrd:value:AVERAGE \
|
||||||
|
DEF:detection_update=${RRDDIR}/counter-flow_detection_update_count.rrd:value:AVERAGE \
|
||||||
|
DEF:guessed=${RRDDIR}/counter-flow_guessed_count.rrd:value:AVERAGE \
|
||||||
|
DEF:detected=${RRDDIR}/counter-flow_detected_count.rrd:value:AVERAGE \
|
||||||
|
DEF:not_detected=${RRDDIR}/counter-flow_not_detected_count.rrd:value:AVERAGE \
|
||||||
|
DEF:analyse=${RRDDIR}/counter-flow_analyse_count.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data init) \
|
||||||
|
AREA:init#f1c232:"Init..................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg init) \
|
||||||
|
STACK:reconnect#63bad9:"Reconnect.............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg reconnect) \
|
||||||
|
STACK:shutdown#3a6f82:"Shutdown..............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg shutdown) \
|
||||||
|
STACK:status#b7cbd1:"Status................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg status) \
|
||||||
|
STACK:packet#0aff3f:"Packet................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg packet) \
|
||||||
|
STACK:packet_flow#00c72b:"Packet-Flow............" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg packet_flow) \
|
||||||
|
STACK:new#c76700:"New...................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg new) \
|
||||||
|
STACK:ewd#c78500:"End...................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg ewd) \
|
||||||
|
STACK:idle#c7a900:"Idle..................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg idle) \
|
||||||
|
STACK:update#c7c400:"Updates................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg update) \
|
||||||
|
STACK:detection_update#a2c700:"Detection-Updates......" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg detection_update) \
|
||||||
|
STACK:guessed#7bc700:"Guessed................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg guessed) \
|
||||||
|
STACK:detected#00c781:"Detected..............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg detected) \
|
||||||
|
STACK:not_detected#00bdc7:"Not-Detected..........." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg not_detected) \
|
||||||
|
STACK:analyse#1400c7:"Analyse................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg analyse)
|
||||||
|
rrdtool_graph Error-Events 'Amount' "${OUTDIR}/error_events" \
|
||||||
|
DEF:error_0=${RRDDIR}/counter-error_unknown_datalink.rrd:value:AVERAGE \
|
||||||
|
DEF:error_1=${RRDDIR}/counter-error_unknown_l3_protocol.rrd:value:AVERAGE \
|
||||||
|
DEF:error_2=${RRDDIR}/counter-error_unsupported_datalink.rrd:value:AVERAGE \
|
||||||
|
DEF:error_3=${RRDDIR}/counter-error_packet_too_short.rrd:value:AVERAGE \
|
||||||
|
DEF:error_4=${RRDDIR}/counter-error_packet_type_unknown.rrd:value:AVERAGE \
|
||||||
|
DEF:error_5=${RRDDIR}/counter-error_packet_header_invalid.rrd:value:AVERAGE \
|
||||||
|
DEF:error_6=${RRDDIR}/counter-error_ip4_packet_too_short.rrd:value:AVERAGE \
|
||||||
|
DEF:error_7=${RRDDIR}/counter-error_ip4_size_smaller_than_header.rrd:value:AVERAGE \
|
||||||
|
DEF:error_8=${RRDDIR}/counter-error_ip4_l4_payload_detection.rrd:value:AVERAGE \
|
||||||
|
DEF:error_9=${RRDDIR}/counter-error_ip6_packet_too_short.rrd:value:AVERAGE \
|
||||||
|
DEF:error_10=${RRDDIR}/counter-error_ip6_size_smaller_than_header.rrd:value:AVERAGE \
|
||||||
|
DEF:error_11=${RRDDIR}/counter-error_ip6_l4_payload_detection.rrd:value:AVERAGE \
|
||||||
|
DEF:error_12=${RRDDIR}/counter-error_tcp_packet_too_short.rrd:value:AVERAGE \
|
||||||
|
DEF:error_13=${RRDDIR}/counter-error_udp_packet_too_short.rrd:value:AVERAGE \
|
||||||
|
DEF:error_14=${RRDDIR}/counter-error_capture_size_smaller_than_packet.rrd:value:AVERAGE \
|
||||||
|
DEF:error_15=${RRDDIR}/counter-error_max_flows_to_track.rrd:value:AVERAGE \
|
||||||
|
DEF:error_16=${RRDDIR}/counter-error_flow_memory_alloc.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data error_0) \
|
||||||
|
AREA:error_0#ff6a00:"Unknown-datalink-layer-packet............................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_0) \
|
||||||
|
STACK:error_1#bf7540:"Unknown-L3-protocol......................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_1) \
|
||||||
|
STACK:error_2#ffd500:"Unsupported-datalink-layer..............................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_2) \
|
||||||
|
STACK:error_3#bfaa40:"Packet-too-short........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_3) \
|
||||||
|
STACK:error_4#bfff00:"Unknown-packet-type......................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_4) \
|
||||||
|
STACK:error_5#9fbf40:"Packet-header-invalid...................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_5) \
|
||||||
|
STACK:error_6#55ff00:"IP4-packet-too-short....................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_6) \
|
||||||
|
STACK:error_7#6abf40:"Packet-smaller-than-IP4-header..........................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_7) \
|
||||||
|
STACK:error_8#00ff15:"nDPI-IPv4/L4-payload-detection-failed...................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_8) \
|
||||||
|
STACK:error_9#40bf4a:"IP6-packet-too-short....................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_9) \
|
||||||
|
STACK:error_10#00ff80:"Packet-smaller-than-IP6-header..........................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_10) \
|
||||||
|
STACK:error_11#40bf80:"nDPI-IPv6/L4-payload-detection-failed...................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_11) \
|
||||||
|
STACK:error_12#00ffea:"TCP-packet-smaller-than-expected........................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_12) \
|
||||||
|
STACK:error_13#40bfb5:"UDP-packet-smaller-than-expected........................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_13) \
|
||||||
|
STACK:error_14#00aaff:"Captured-packet-size-is-smaller-than-expected-packet-size" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_14) \
|
||||||
|
STACK:error_15#4095bf:"Max-flows-to-track-reached..............................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_15) \
|
||||||
|
STACK:error_16#0040ff:"Flow-memory-allocation-failed............................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg error_16)
|
||||||
|
rrdtool_graph Risk-Severites Amount "${OUTDIR}/severities" \
|
||||||
|
DEF:sever_crit=${RRDDIR}/gauge-flow_severity_critical.rrd:value:AVERAGE \
|
||||||
|
DEF:sever_emer=${RRDDIR}/gauge-flow_severity_emergency.rrd:value:AVERAGE \
|
||||||
|
DEF:sever_high=${RRDDIR}/gauge-flow_severity_high.rrd:value:AVERAGE \
|
||||||
|
DEF:sever_low=${RRDDIR}/gauge-flow_severity_low.rrd:value:AVERAGE \
|
||||||
|
DEF:sever_med=${RRDDIR}/gauge-flow_severity_medium.rrd:value:AVERAGE \
|
||||||
|
DEF:sever_sev=${RRDDIR}/gauge-flow_severity_severe.rrd:value:AVERAGE \
|
||||||
|
DEF:sever_ukn=${RRDDIR}/gauge-flow_severity_unknown.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data sever_crit) \
|
||||||
|
AREA:sever_crit#e68e00::STACK \
|
||||||
|
AREA:sever_emer#e63200::STACK \
|
||||||
|
AREA:sever_high#e6c700::STACK \
|
||||||
|
AREA:sever_low#00e600::STACK \
|
||||||
|
AREA:sever_med#8fce00::STACK \
|
||||||
|
AREA:sever_sev#c61b2b::STACK \
|
||||||
|
AREA:sever_ukn#7e8877::STACK \
|
||||||
|
LINE2:sever_crit#e68e00:"Critical............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg sever_crit) \
|
||||||
|
LINE2:sever_emer#e63200:"Emergency............" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg sever_emer) \
|
||||||
|
LINE2:sever_high#e6c700:"High................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg sever_high) \
|
||||||
|
LINE2:sever_low#00e600:"Low.................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg sever_low) \
|
||||||
|
LINE2:sever_med#8fce00:"Medium..............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg sever_med) \
|
||||||
|
LINE2:sever_sev#c61b2b:"Severe..............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg sever_sev) \
|
||||||
|
LINE2:sever_ukn#7e8877:"Unknown.............." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg sever_ukn)
|
||||||
|
rrdtool_graph Risks 'Amount' "${OUTDIR}/risky_events" \
|
||||||
|
DEF:risk_1=${RRDDIR}/gauge-flow_risk_1_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_2=${RRDDIR}/gauge-flow_risk_2_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_3=${RRDDIR}/gauge-flow_risk_3_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_4=${RRDDIR}/gauge-flow_risk_4_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_5=${RRDDIR}/gauge-flow_risk_5_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_6=${RRDDIR}/gauge-flow_risk_6_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_7=${RRDDIR}/gauge-flow_risk_7_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_8=${RRDDIR}/gauge-flow_risk_8_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_9=${RRDDIR}/gauge-flow_risk_9_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_10=${RRDDIR}/gauge-flow_risk_10_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_11=${RRDDIR}/gauge-flow_risk_11_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_12=${RRDDIR}/gauge-flow_risk_12_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_13=${RRDDIR}/gauge-flow_risk_13_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_14=${RRDDIR}/gauge-flow_risk_14_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_15=${RRDDIR}/gauge-flow_risk_15_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_16=${RRDDIR}/gauge-flow_risk_16_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_17=${RRDDIR}/gauge-flow_risk_17_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_18=${RRDDIR}/gauge-flow_risk_18_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_19=${RRDDIR}/gauge-flow_risk_19_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_20=${RRDDIR}/gauge-flow_risk_20_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_21=${RRDDIR}/gauge-flow_risk_21_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_22=${RRDDIR}/gauge-flow_risk_22_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_23=${RRDDIR}/gauge-flow_risk_23_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_24=${RRDDIR}/gauge-flow_risk_24_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_25=${RRDDIR}/gauge-flow_risk_25_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_26=${RRDDIR}/gauge-flow_risk_26_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_27=${RRDDIR}/gauge-flow_risk_27_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_28=${RRDDIR}/gauge-flow_risk_28_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_29=${RRDDIR}/gauge-flow_risk_29_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_30=${RRDDIR}/gauge-flow_risk_30_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_31=${RRDDIR}/gauge-flow_risk_31_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_32=${RRDDIR}/gauge-flow_risk_32_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_33=${RRDDIR}/gauge-flow_risk_33_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_34=${RRDDIR}/gauge-flow_risk_34_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_35=${RRDDIR}/gauge-flow_risk_35_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_36=${RRDDIR}/gauge-flow_risk_36_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_37=${RRDDIR}/gauge-flow_risk_37_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_38=${RRDDIR}/gauge-flow_risk_38_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_39=${RRDDIR}/gauge-flow_risk_39_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_40=${RRDDIR}/gauge-flow_risk_40_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_41=${RRDDIR}/gauge-flow_risk_41_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_42=${RRDDIR}/gauge-flow_risk_42_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_43=${RRDDIR}/gauge-flow_risk_43_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_44=${RRDDIR}/gauge-flow_risk_44_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_45=${RRDDIR}/gauge-flow_risk_45_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_46=${RRDDIR}/gauge-flow_risk_46_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_47=${RRDDIR}/gauge-flow_risk_47_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_48=${RRDDIR}/gauge-flow_risk_48_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_49=${RRDDIR}/gauge-flow_risk_49_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_50=${RRDDIR}/gauge-flow_risk_50_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_51=${RRDDIR}/gauge-flow_risk_51_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_52=${RRDDIR}/gauge-flow_risk_52_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_53=${RRDDIR}/gauge-flow_risk_53_count.rrd:value:AVERAGE \
|
||||||
|
DEF:risk_unknown=${RRDDIR}/gauge-flow_risk_unknown_count.rrd:value:AVERAGE \
|
||||||
|
$(rrdtool_graph_colorize_missing_data risk_1) \
|
||||||
|
AREA:risk_1#ff0000:"XSS-Attack..............................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_1) \
|
||||||
|
STACK:risk_2#ff5500:"SQL-Injection............................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_2) \
|
||||||
|
STACK:risk_3#ffaa00:"RCE-Injection............................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_3) \
|
||||||
|
STACK:risk_4#ffff00:"Binary-App-Transfer......................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_4) \
|
||||||
|
STACK:risk_5#aaff00:"Known-Proto-on-Non-Std-Port.............................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_5) \
|
||||||
|
STACK:risk_6#55ff00:"Self-signed-Cert........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_6) \
|
||||||
|
STACK:risk_7#00ff55:"Obsolete-TLS-v1.1-or-older..............................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_7) \
|
||||||
|
STACK:risk_8#00ffaa:"Weak-TLS-Cipher.........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_8) \
|
||||||
|
STACK:risk_9#00ffff:"TLS-Cert-Expired........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_9) \
|
||||||
|
STACK:risk_10#00aaff:"TLS-Cert-Mismatch........................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_10) \
|
||||||
|
STACK:risk_11#0055ff:"HTTP-Suspicious-User-Agent..............................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_11) \
|
||||||
|
STACK:risk_12#0000ff:"HTTP-Numeric-IP-Address.................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_12) \
|
||||||
|
STACK:risk_13#5500ff:"HTTP-Suspicious-URL......................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_13) \
|
||||||
|
STACK:risk_14#aa00ff:"HTTP-Suspicious-Header..................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_14) \
|
||||||
|
STACK:risk_15#ff00ff:"TLS-probably-Not-Carrying-HTTPS.........................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_15) \
|
||||||
|
STACK:risk_16#ff00aa:"Suspicious-DGA-Domain-name..............................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_16) \
|
||||||
|
STACK:risk_17#ff0055:"Malformed-Packet........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_17) \
|
||||||
|
STACK:risk_18#602020:"SSH-Obsolete-Client-Version/Cipher......................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_18) \
|
||||||
|
STACK:risk_19#603a20:"SSH-Obsolete-Server-Version/Cipher......................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_19) \
|
||||||
|
STACK:risk_20#605520:"SMB-Insecure-Version....................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_20) \
|
||||||
|
STACK:risk_21#506020:"TLS-Suspicious-ESNI-Usage................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_21) \
|
||||||
|
STACK:risk_22#356020:"Unsafe-Protocol.........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_22) \
|
||||||
|
STACK:risk_23#206025:"Suspicious-DNS-Traffic..................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_23) \
|
||||||
|
STACK:risk_24#206040:"Missing-SNI-TLS-Extension................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_24) \
|
||||||
|
STACK:risk_25#20605a:"HTTP-Suspicious-Content.................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_25) \
|
||||||
|
STACK:risk_26#204a60:"Risky-ASN................................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_26) \
|
||||||
|
STACK:risk_27#203060:"Risky-Domain-Name........................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_27) \
|
||||||
|
STACK:risk_28#2a2060:"Malicious-JA3-Fingerprint................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_28) \
|
||||||
|
STACK:risk_29#452060:"Malicious-SSL-Cert/SHA1-Fingerprint......................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_29) \
|
||||||
|
STACK:risk_30#602060:"Desktop/File-Sharing....................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_30) \
|
||||||
|
STACK:risk_31#602045:"Uncommon-TLS-ALPN........................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_31) \
|
||||||
|
STACK:risk_32#df2020:"TLS-Cert-Validity-Too-Long..............................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_32) \
|
||||||
|
STACK:risk_33#df6020:"TLS-Suspicious-Extension................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_33) \
|
||||||
|
STACK:risk_34#df9f20:"TLS-Fatal-Alert.........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_34) \
|
||||||
|
STACK:risk_35#dfdf20:"Suspicious-Entropy......................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_35) \
|
||||||
|
STACK:risk_36#9fdf20:"Clear-Text-Credentials..................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_36) \
|
||||||
|
STACK:risk_37#60df20:"Large-DNS-Packet........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_37) \
|
||||||
|
STACK:risk_38#20df20:"Fragmented-DNS-Message..................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_38) \
|
||||||
|
STACK:risk_39#20df60:"Text-With-Non-Printable-Chars............................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_39) \
|
||||||
|
STACK:risk_40#20df9f:"Possible-Exploit........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_40) \
|
||||||
|
STACK:risk_41#20dfdf:"TLS-Cert-About-To-Expire................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_41) \
|
||||||
|
STACK:risk_42#209fdf:"IDN-Domain-Name.........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_42) \
|
||||||
|
STACK:risk_43#2060df:"Error-Code..............................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_43) \
|
||||||
|
STACK:risk_44#2020df:"Crawler/Bot.............................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_44) \
|
||||||
|
STACK:risk_45#6020df:"Anonymous-Subscriber....................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_45) \
|
||||||
|
STACK:risk_46#9f20df:"Unidirectional-Traffic..................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_46) \
|
||||||
|
STACK:risk_47#df20df:"HTTP-Obsolete-Server....................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_47) \
|
||||||
|
STACK:risk_48#df68df:"Periodic-Flow............................................" \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_48) \
|
||||||
|
STACK:risk_49#dfffdf:"Minor-Issues............................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_49) \
|
||||||
|
STACK:risk_50#ef20df:"TCP-Connection-Issues...................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_50) \
|
||||||
|
STACK:risk_51#ef60df:"Fully-Encrypted.........................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_51) \
|
||||||
|
STACK:risk_52#efa0df:"Invalid-ALPN/SNI-combination............................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_52) \
|
||||||
|
STACK:risk_53#efffdf:"Malware-Host-Contacted..................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_53) \
|
||||||
|
STACK:risk_unknown#df2060:"Unknown.................................................." \
|
||||||
|
$(rrdtool_graph_print_cur_min_max_avg risk_unknown)
|
||||||
7
examples/c-collectd/www/dpi/bootstrap.css
vendored
Normal file
7
examples/c-collectd/www/dpi/bootstrap.css
vendored
Normal file
File diff suppressed because one or more lines are too long
7
examples/c-collectd/www/dpi/bootstrap.js
vendored
Normal file
7
examples/c-collectd/www/dpi/bootstrap.js
vendored
Normal file
File diff suppressed because one or more lines are too long
198
examples/c-collectd/www/dpi/categories.html
Normal file
198
examples/c-collectd/www/dpi/categories.html
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head>
|
||||||
|
<meta http-equiv="cache-control" content="max-age=0" />
|
||||||
|
<meta http-equiv="cache-control" content="no-cache" />
|
||||||
|
<meta http-equiv="expires" content="0" />
|
||||||
|
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
|
||||||
|
<meta http-equiv="pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="nDPId RRD Graph">
|
||||||
|
<meta name="author" content="Toni Uhlig">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/4.0/assets/img/favicons/favicon.ico">
|
||||||
|
|
||||||
|
<title>nDPId Dashboard</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/dashboard/">
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="bootstrap.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="dashboard.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
|
||||||
|
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="https://github.com/utoni/nDPId">nDPId Collectd RRD Graph</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
|
||||||
|
<div class="sidebar-sticky">
|
||||||
|
|
||||||
|
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||||
|
<span>Graphs</span>
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<ul class="nav flex-column mb-2">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="flows.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Flows
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="other.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Other
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="detections.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Detections
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="categories.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Categories
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="risks.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Risks
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="jsons.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
JSONs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="events.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Events
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="jquery-3.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||||
|
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
|
||||||
|
<script src="popper.js"></script>
|
||||||
|
<script src="bootstrap.js"></script>
|
||||||
|
|
||||||
|
<!-- Icons -->
|
||||||
|
<script src="feather.js"></script>
|
||||||
|
<script>
|
||||||
|
feather.replace()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
93
examples/c-collectd/www/dpi/dashboard.css
Normal file
93
examples/c-collectd/www/dpi/dashboard.css
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
body {
|
||||||
|
font-size: .875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feather {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sidebar
|
||||||
|
*/
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 100; /* Behind the navbar */
|
||||||
|
padding: 0;
|
||||||
|
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-sticky {
|
||||||
|
position: -webkit-sticky;
|
||||||
|
position: sticky;
|
||||||
|
top: 48px; /* Height of navbar */
|
||||||
|
height: calc(100vh - 48px);
|
||||||
|
padding-top: .5rem;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar .nav-link {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar .nav-link .feather {
|
||||||
|
margin-right: 4px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar .nav-link.active {
|
||||||
|
color: #007bff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar .nav-link:hover .feather,
|
||||||
|
.sidebar .nav-link.active .feather {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-heading {
|
||||||
|
font-size: .75rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Navbar
|
||||||
|
*/
|
||||||
|
|
||||||
|
.navbar-brand {
|
||||||
|
padding-top: .75rem;
|
||||||
|
padding-bottom: .75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
background-color: rgba(0, 0, 0, .25);
|
||||||
|
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .form-control {
|
||||||
|
padding: .75rem 1rem;
|
||||||
|
border-width: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-dark {
|
||||||
|
color: #fff;
|
||||||
|
background-color: rgba(255, 255, 255, .1);
|
||||||
|
border-color: rgba(255, 255, 255, .1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-dark:focus {
|
||||||
|
border-color: transparent;
|
||||||
|
box-shadow: 0 0 0 3px rgba(255, 255, 255, .25);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utilities
|
||||||
|
*/
|
||||||
|
|
||||||
|
.border-top { border-top: 1px solid #e5e5e5; }
|
||||||
|
.border-bottom { border-bottom: 1px solid #e5e5e5; }
|
||||||
198
examples/c-collectd/www/dpi/detections.html
Normal file
198
examples/c-collectd/www/dpi/detections.html
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head>
|
||||||
|
<meta http-equiv="cache-control" content="max-age=0" />
|
||||||
|
<meta http-equiv="cache-control" content="no-cache" />
|
||||||
|
<meta http-equiv="expires" content="0" />
|
||||||
|
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
|
||||||
|
<meta http-equiv="pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="nDPId RRD Graph">
|
||||||
|
<meta name="author" content="Toni Uhlig">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/4.0/assets/img/favicons/favicon.ico">
|
||||||
|
|
||||||
|
<title>nDPId Dashboard</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/dashboard/">
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="bootstrap.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="dashboard.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
|
||||||
|
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="https://github.com/utoni/nDPId">nDPId Collectd RRD Graph</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
|
||||||
|
<div class="sidebar-sticky">
|
||||||
|
|
||||||
|
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||||
|
<span>Graphs</span>
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<ul class="nav flex-column mb-2">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="flows.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Flows
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="other.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Other
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="detections.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Detections
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="categories.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Categories
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="risks.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Risks
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="jsons.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
JSONs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="events.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Events
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="jquery-3.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||||
|
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
|
||||||
|
<script src="popper.js"></script>
|
||||||
|
<script src="bootstrap.js"></script>
|
||||||
|
|
||||||
|
<!-- Icons -->
|
||||||
|
<script src="feather.js"></script>
|
||||||
|
<script>
|
||||||
|
feather.replace()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
198
examples/c-collectd/www/dpi/events.html
Normal file
198
examples/c-collectd/www/dpi/events.html
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head>
|
||||||
|
<meta http-equiv="cache-control" content="max-age=0" />
|
||||||
|
<meta http-equiv="cache-control" content="no-cache" />
|
||||||
|
<meta http-equiv="expires" content="0" />
|
||||||
|
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
|
||||||
|
<meta http-equiv="pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="nDPId RRD Graph">
|
||||||
|
<meta name="author" content="Toni Uhlig">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/4.0/assets/img/favicons/favicon.ico">
|
||||||
|
|
||||||
|
<title>nDPId Dashboard</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/dashboard/">
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="bootstrap.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="dashboard.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
|
||||||
|
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="https://github.com/utoni/nDPId">nDPId Collectd RRD Graph</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
|
||||||
|
<div class="sidebar-sticky">
|
||||||
|
|
||||||
|
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||||
|
<span>Graphs</span>
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<ul class="nav flex-column mb-2">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="flows.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Flows
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="other.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Other
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="detections.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Detections
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="categories.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Categories
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="risks.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Risks
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="jsons.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
JSONs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="events.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Events
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="jquery-3.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||||
|
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
|
||||||
|
<script src="popper.js"></script>
|
||||||
|
<script src="bootstrap.js"></script>
|
||||||
|
|
||||||
|
<!-- Icons -->
|
||||||
|
<script src="feather.js"></script>
|
||||||
|
<script>
|
||||||
|
feather.replace()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
13
examples/c-collectd/www/dpi/feather.js
Normal file
13
examples/c-collectd/www/dpi/feather.js
Normal file
File diff suppressed because one or more lines are too long
179
examples/c-collectd/www/dpi/flows.html
Normal file
179
examples/c-collectd/www/dpi/flows.html
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head>
|
||||||
|
<meta http-equiv="cache-control" content="max-age=0" />
|
||||||
|
<meta http-equiv="cache-control" content="no-cache" />
|
||||||
|
<meta http-equiv="expires" content="0" />
|
||||||
|
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
|
||||||
|
<meta http-equiv="pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="nDPId RRD Graph">
|
||||||
|
<meta name="author" content="Toni Uhlig">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/4.0/assets/img/favicons/favicon.ico">
|
||||||
|
|
||||||
|
<title>nDPId Dashboard</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/dashboard/">
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="bootstrap.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="dashboard.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
|
||||||
|
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="https://github.com/utoni/nDPId">nDPId Collectd RRD Graph</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
|
||||||
|
<div class="sidebar-sticky">
|
||||||
|
|
||||||
|
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||||
|
<span>Graphs</span>
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<ul class="nav flex-column mb-2">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="flows.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Flows
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="other.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Other
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="detections.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Detections
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="categories.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Categories
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="risks.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Risks
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="jsons.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
JSONs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="events.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Events
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="jquery-3.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||||
|
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
|
||||||
|
<script src="popper.js"></script>
|
||||||
|
<script src="bootstrap.js"></script>
|
||||||
|
|
||||||
|
<!-- Icons -->
|
||||||
|
<script src="feather.js"></script>
|
||||||
|
<script>
|
||||||
|
feather.replace()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
425
examples/c-collectd/www/dpi/index.html
Normal file
425
examples/c-collectd/www/dpi/index.html
Normal file
@@ -0,0 +1,425 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head>
|
||||||
|
<meta http-equiv="cache-control" content="max-age=0" />
|
||||||
|
<meta http-equiv="cache-control" content="no-cache" />
|
||||||
|
<meta http-equiv="expires" content="0" />
|
||||||
|
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
|
||||||
|
<meta http-equiv="pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="nDPId RRD Graph">
|
||||||
|
<meta name="author" content="Toni Uhlig">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/4.0/assets/img/favicons/favicon.ico">
|
||||||
|
|
||||||
|
<title>nDPId Dashboard</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/dashboard/">
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="bootstrap.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="dashboard.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
|
||||||
|
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="https://github.com/utoni/nDPId">nDPId Collectd RRD Graph</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
|
||||||
|
<div class="sidebar-sticky">
|
||||||
|
|
||||||
|
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||||
|
<span>Graphs</span>
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<ul class="nav flex-column mb-2">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="index.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="flows.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Flows
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="other.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Other
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="detections.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Detections
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="categories.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Categories
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="risks.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Risks
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="jsons.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
JSONs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="events.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Events
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="flows_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="detections_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="confidence_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="breed_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="categories_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="events_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="error_events_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="jquery-3.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||||
|
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
|
||||||
|
<script src="popper.js"></script>
|
||||||
|
<script src="bootstrap.js"></script>
|
||||||
|
|
||||||
|
<!-- Icons -->
|
||||||
|
<script src="feather.js"></script>
|
||||||
|
<script>
|
||||||
|
feather.replace()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
4
examples/c-collectd/www/dpi/jquery-3.js
vendored
Normal file
4
examples/c-collectd/www/dpi/jquery-3.js
vendored
Normal file
File diff suppressed because one or more lines are too long
198
examples/c-collectd/www/dpi/jsons.html
Normal file
198
examples/c-collectd/www/dpi/jsons.html
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head>
|
||||||
|
<meta http-equiv="cache-control" content="max-age=0" />
|
||||||
|
<meta http-equiv="cache-control" content="no-cache" />
|
||||||
|
<meta http-equiv="expires" content="0" />
|
||||||
|
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
|
||||||
|
<meta http-equiv="pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="nDPId RRD Graph">
|
||||||
|
<meta name="author" content="Toni Uhlig">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/4.0/assets/img/favicons/favicon.ico">
|
||||||
|
|
||||||
|
<title>nDPId Dashboard</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/dashboard/">
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="bootstrap.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="dashboard.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
|
||||||
|
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="https://github.com/utoni/nDPId">nDPId Collectd RRD Graph</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
|
||||||
|
<div class="sidebar-sticky">
|
||||||
|
|
||||||
|
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||||
|
<span>Graphs</span>
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<ul class="nav flex-column mb-2">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="flows.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Flows
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="other.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Other
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="detections.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Detections
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="categories.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Categories
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="risks.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Risks
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="jsons.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
JSONs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="events.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Events
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_lines_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="json_bytes_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="jquery-3.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||||
|
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
|
||||||
|
<script src="popper.js"></script>
|
||||||
|
<script src="bootstrap.js"></script>
|
||||||
|
|
||||||
|
<!-- Icons -->
|
||||||
|
<script src="feather.js"></script>
|
||||||
|
<script>
|
||||||
|
feather.replace()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
217
examples/c-collectd/www/dpi/other.html
Normal file
217
examples/c-collectd/www/dpi/other.html
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head>
|
||||||
|
<meta http-equiv="cache-control" content="max-age=0" />
|
||||||
|
<meta http-equiv="cache-control" content="no-cache" />
|
||||||
|
<meta http-equiv="expires" content="0" />
|
||||||
|
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
|
||||||
|
<meta http-equiv="pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="nDPId RRD Graph">
|
||||||
|
<meta name="author" content="Toni Uhlig">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/4.0/assets/img/favicons/favicon.ico">
|
||||||
|
|
||||||
|
<title>nDPId Dashboard</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/dashboard/">
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="bootstrap.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="dashboard.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
|
||||||
|
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="https://github.com/utoni/nDPId">nDPId Collectd RRD Graph</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
|
||||||
|
<div class="sidebar-sticky">
|
||||||
|
|
||||||
|
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||||
|
<span>Graphs</span>
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<ul class="nav flex-column mb-2">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="flows.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Flows
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="other.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Other
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="detections.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Detections
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="categories.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Categories
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="risks.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Risks
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="jsons.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
JSONs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="events.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Events
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="traffic_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer3_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="layer4_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="jquery-3.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||||
|
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
|
||||||
|
<script src="popper.js"></script>
|
||||||
|
<script src="bootstrap.js"></script>
|
||||||
|
|
||||||
|
<!-- Icons -->
|
||||||
|
<script src="feather.js"></script>
|
||||||
|
<script>
|
||||||
|
feather.replace()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
5
examples/c-collectd/www/dpi/popper.js
Normal file
5
examples/c-collectd/www/dpi/popper.js
Normal file
File diff suppressed because one or more lines are too long
198
examples/c-collectd/www/dpi/risks.html
Normal file
198
examples/c-collectd/www/dpi/risks.html
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en"><head>
|
||||||
|
<meta http-equiv="cache-control" content="max-age=0" />
|
||||||
|
<meta http-equiv="cache-control" content="no-cache" />
|
||||||
|
<meta http-equiv="expires" content="0" />
|
||||||
|
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
|
||||||
|
<meta http-equiv="pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="nDPId RRD Graph">
|
||||||
|
<meta name="author" content="Toni Uhlig">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/4.0/assets/img/favicons/favicon.ico">
|
||||||
|
|
||||||
|
<title>nDPId Dashboard</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/dashboard/">
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="bootstrap.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="dashboard.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
|
||||||
|
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="https://github.com/utoni/nDPId">nDPId Collectd RRD Graph</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
|
||||||
|
<div class="sidebar-sticky">
|
||||||
|
|
||||||
|
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||||
|
<span>Graphs</span>
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<ul class="nav flex-column mb-2">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Home
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="flows.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Flows
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="other.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Other
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="detections.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Detections
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="categories.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Categories
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="risks.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Risks
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="jsons.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
JSONs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="events.html">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
|
||||||
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||||
|
<polyline points="14 2 14 8 20 8"></polyline>
|
||||||
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||||
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||||
|
<polyline points="10 9 9 9 8 9"></polyline>
|
||||||
|
</svg>
|
||||||
|
Events
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="severities_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_hour.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_12hours.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_day.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_week.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_month.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<img src="risky_events_past_year.png" class="img-fluid" alt="Responsive image">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
|
<script src="jquery-3.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||||
|
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
|
||||||
|
<script src="popper.js"></script>
|
||||||
|
<script src="bootstrap.js"></script>
|
||||||
|
|
||||||
|
<!-- Icons -->
|
||||||
|
<script src="feather.js"></script>
|
||||||
|
<script>
|
||||||
|
feather.replace()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body></html>
|
||||||
1921
examples/c-influxd/c-influxd.c
Normal file
1921
examples/c-influxd/c-influxd.c
Normal file
File diff suppressed because it is too large
Load Diff
6021
examples/c-influxd/grafana-dashboard-simple.json
Normal file
6021
examples/c-influxd/grafana-dashboard-simple.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,135 +0,0 @@
|
|||||||
#include <arpa/inet.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "jsmn.h"
|
|
||||||
|
|
||||||
static char serv_listen_addr[INET_ADDRSTRLEN] = DISTRIBUTOR_HOST;
|
|
||||||
static uint16_t serv_listen_port = DISTRIBUTOR_PORT;
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
struct sockaddr_in remote_addr = {};
|
|
||||||
socklen_t remote_addrlen = sizeof(remote_addr);
|
|
||||||
uint8_t buf[NETWORK_BUFFER_MAX_SIZE];
|
|
||||||
size_t buf_used = 0;
|
|
||||||
size_t json_start = 0;
|
|
||||||
unsigned long long int json_bytes = 0;
|
|
||||||
jsmn_parser parser;
|
|
||||||
jsmntok_t tokens[128];
|
|
||||||
|
|
||||||
if (sockfd < 0)
|
|
||||||
{
|
|
||||||
perror("socket");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
remote_addr.sin_family = AF_INET;
|
|
||||||
if (inet_pton(AF_INET, &serv_listen_addr[0], &remote_addr.sin_addr) != 1)
|
|
||||||
{
|
|
||||||
perror("inet_pton");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
remote_addr.sin_port = htons(serv_listen_port);
|
|
||||||
|
|
||||||
if (connect(sockfd, (struct sockaddr *)&remote_addr, remote_addrlen) != 0)
|
|
||||||
{
|
|
||||||
perror("connect");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
ssize_t bytes_read = read(sockfd, buf + buf_used, sizeof(buf) - buf_used);
|
|
||||||
|
|
||||||
if (bytes_read <= 0 || errno != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Remote end disconnected.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf_used += bytes_read;
|
|
||||||
while (buf_used >= NETWORK_BUFFER_LENGTH_DIGITS + 1)
|
|
||||||
{
|
|
||||||
if (buf[NETWORK_BUFFER_LENGTH_DIGITS] != '{')
|
|
||||||
{
|
|
||||||
fprintf(stderr, "BUG: JSON invalid opening character: '%c'\n", buf[NETWORK_BUFFER_LENGTH_DIGITS]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char * json_str_start = NULL;
|
|
||||||
json_bytes = strtoull((char *)buf, &json_str_start, 10);
|
|
||||||
json_bytes += (uint8_t *)json_str_start - buf;
|
|
||||||
json_start = (uint8_t *)json_str_start - buf;
|
|
||||||
|
|
||||||
if (errno == ERANGE)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "BUG: Size of JSON exceeds limit\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if ((uint8_t *)json_str_start == buf)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "BUG: Missing size before JSON string: \"%.*s\"\n", NETWORK_BUFFER_LENGTH_DIGITS, buf);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (json_bytes > sizeof(buf))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "BUG: JSON string too big: %llu > %zu\n", json_bytes, sizeof(buf));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (json_bytes > buf_used)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf[json_bytes - 2] != '}' ||
|
|
||||||
buf[json_bytes - 1] != '\n')
|
|
||||||
{
|
|
||||||
fprintf(stderr, "BUG: Invalid JSON string: \"%.*s\"\n", (int)json_bytes, buf);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int r;
|
|
||||||
jsmn_init(&parser);
|
|
||||||
r = jsmn_parse(&parser,
|
|
||||||
(char *)(buf + json_start),
|
|
||||||
json_bytes - json_start,
|
|
||||||
tokens,
|
|
||||||
sizeof(tokens) / sizeof(tokens[0]));
|
|
||||||
if (r < 0 || tokens[0].type != JSMN_OBJECT)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "JSON parsing failed with return value %d at position %u\n", r, parser.pos);
|
|
||||||
fprintf(stderr, "JSON string: '%.*s'\n", (int)(json_bytes - json_start), (char *)(buf + json_start));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i < r; i++)
|
|
||||||
{
|
|
||||||
if (i % 2 == 1)
|
|
||||||
{
|
|
||||||
printf("[%.*s : ", tokens[i].end - tokens[i].start, (char *)(buf + json_start) + tokens[i].start);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("%.*s] ", tokens[i].end - tokens[i].start, (char *)(buf + json_start) + tokens[i].start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("EoF\n");
|
|
||||||
|
|
||||||
memmove(buf, buf + json_bytes, buf_used - json_bytes);
|
|
||||||
buf_used -= json_bytes;
|
|
||||||
json_bytes = 0;
|
|
||||||
json_start = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
714
examples/c-notifyd/c-notifyd.c
Normal file
714
examples/c-notifyd/c-notifyd.c
Normal file
@@ -0,0 +1,714 @@
|
|||||||
|
#include <dbus-1.0/dbus/dbus.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "nDPIsrvd.h"
|
||||||
|
#include "utstring.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#define SLEEP_TIME_IN_S (3)
|
||||||
|
|
||||||
|
struct flow_user_data
|
||||||
|
{
|
||||||
|
nDPIsrvd_ull detected_risks;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dbus_level
|
||||||
|
{
|
||||||
|
DBUS_LOW = 0,
|
||||||
|
DBUS_NORMAL,
|
||||||
|
DBUS_CRITICAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static char const * const flow_severities[] = {"Low", "Medium", "High", "Severe", "Critical", "Emergency"};
|
||||||
|
static char const * const flow_breeds[] = {
|
||||||
|
"Safe", "Acceptable", "Fun", "Unsafe", "Potentially_Dangerous", "Tracker_Ads", "Dangerous", "Unrated", "???"};
|
||||||
|
static char const * const flow_categories[] = {"Unspecified",
|
||||||
|
"Media",
|
||||||
|
"VPN",
|
||||||
|
"Email",
|
||||||
|
"DataTransfer",
|
||||||
|
"Web",
|
||||||
|
"SocialNetwork",
|
||||||
|
"Download",
|
||||||
|
"Game",
|
||||||
|
"Chat",
|
||||||
|
"VoIP",
|
||||||
|
"Database",
|
||||||
|
"RemoteAccess",
|
||||||
|
"Cloud",
|
||||||
|
"Network",
|
||||||
|
"Collaborative",
|
||||||
|
"RPC",
|
||||||
|
"Streaming",
|
||||||
|
"System",
|
||||||
|
"SoftwareUpdate",
|
||||||
|
"Music",
|
||||||
|
"Video",
|
||||||
|
"Shopping",
|
||||||
|
"Productivity",
|
||||||
|
"FileSharing",
|
||||||
|
"ConnCheck",
|
||||||
|
"IoT-Scada",
|
||||||
|
"VirtAssistant",
|
||||||
|
"Cybersecurity",
|
||||||
|
"AdultContent",
|
||||||
|
"Mining",
|
||||||
|
"Malware",
|
||||||
|
"Advertisement",
|
||||||
|
"Banned_Site",
|
||||||
|
"Site_Unavailable",
|
||||||
|
"Allowed_Site",
|
||||||
|
"Antimalware",
|
||||||
|
"Crypto_Currency",
|
||||||
|
"Gambling",
|
||||||
|
"Health",
|
||||||
|
"ArtifIntelligence",
|
||||||
|
"Finance",
|
||||||
|
"News",
|
||||||
|
"Sport",
|
||||||
|
"Business",
|
||||||
|
"Internet",
|
||||||
|
"Blockchain_Crypto",
|
||||||
|
"Blog_Forum",
|
||||||
|
"Government",
|
||||||
|
"Education",
|
||||||
|
"CDN_Proxy",
|
||||||
|
"Hw_Sw",
|
||||||
|
"Dating",
|
||||||
|
"Travel",
|
||||||
|
"Food",
|
||||||
|
"Bots",
|
||||||
|
"Scanners",
|
||||||
|
"Hosting",
|
||||||
|
"Art",
|
||||||
|
"Fashion",
|
||||||
|
"Books",
|
||||||
|
"Science",
|
||||||
|
"Maps_Navigation",
|
||||||
|
"Login_Portal",
|
||||||
|
"Legal",
|
||||||
|
"Environmental_Services",
|
||||||
|
"Culture",
|
||||||
|
"Housing",
|
||||||
|
"Telecommunication",
|
||||||
|
"Transportation",
|
||||||
|
"Design",
|
||||||
|
"Employment",
|
||||||
|
"Events",
|
||||||
|
"Weather",
|
||||||
|
"Lifestyle",
|
||||||
|
"Real_Estate",
|
||||||
|
"Security",
|
||||||
|
"Environment",
|
||||||
|
"Hobby",
|
||||||
|
"Computer_Science",
|
||||||
|
"Construction",
|
||||||
|
"Engineering",
|
||||||
|
"Religion",
|
||||||
|
"Entertainment",
|
||||||
|
"Agriculture",
|
||||||
|
"Technology",
|
||||||
|
"Beauty",
|
||||||
|
"History",
|
||||||
|
"Politics",
|
||||||
|
"Vehicles"};
|
||||||
|
|
||||||
|
static uint8_t desired_flow_severities[nDPIsrvd_ARRAY_LENGTH(flow_severities)] = {};
|
||||||
|
static uint8_t desired_flow_breeds[nDPIsrvd_ARRAY_LENGTH(flow_breeds)] = {};
|
||||||
|
static uint8_t desired_flow_categories[nDPIsrvd_ARRAY_LENGTH(flow_categories)] = {};
|
||||||
|
|
||||||
|
static unsigned int id = 0;
|
||||||
|
static char const * const application = "nDPIsrvd.notifyd";
|
||||||
|
|
||||||
|
static int main_thread_shutdown = 0;
|
||||||
|
|
||||||
|
static char * pidfile = NULL;
|
||||||
|
static char * serv_optarg = NULL;
|
||||||
|
|
||||||
|
#ifdef ENABLE_MEMORY_PROFILING
|
||||||
|
void nDPIsrvd_memprof_log_alloc(size_t alloc_size)
|
||||||
|
{
|
||||||
|
(void)alloc_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nDPIsrvd_memprof_log_free(size_t free_size)
|
||||||
|
{
|
||||||
|
(void)free_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nDPIsrvd_memprof_log(char const * const format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
fprintf(stderr, "%s", "nDPIsrvd MemoryProfiler: ");
|
||||||
|
vfprintf(stderr, format, ap);
|
||||||
|
fprintf(stderr, "%s\n", "");
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void send_to_dbus(char const * const icon,
|
||||||
|
char const * const urgency,
|
||||||
|
enum dbus_level level,
|
||||||
|
char const * const summary,
|
||||||
|
char const * const body,
|
||||||
|
int timeout)
|
||||||
|
{
|
||||||
|
DBusConnection * connection = dbus_bus_get(DBUS_BUS_SESSION, 0);
|
||||||
|
DBusMessage * message = dbus_message_new_method_call("org.freedesktop.Notifications",
|
||||||
|
"/org/freedesktop/Notifications",
|
||||||
|
"org.freedesktop.Notifications",
|
||||||
|
"Notify");
|
||||||
|
DBusMessageIter iter[4];
|
||||||
|
dbus_message_iter_init_append(message, iter);
|
||||||
|
dbus_message_iter_append_basic(iter, 's', &application);
|
||||||
|
dbus_message_iter_append_basic(iter, 'u', &id);
|
||||||
|
dbus_message_iter_append_basic(iter, 's', &icon);
|
||||||
|
dbus_message_iter_append_basic(iter, 's', &summary);
|
||||||
|
dbus_message_iter_append_basic(iter, 's', &body);
|
||||||
|
dbus_message_iter_open_container(iter, 'a', "s", iter + 1);
|
||||||
|
dbus_message_iter_close_container(iter, iter + 1);
|
||||||
|
dbus_message_iter_open_container(iter, 'a', "{sv}", iter + 1);
|
||||||
|
dbus_message_iter_open_container(iter + 1, 'e', 0, iter + 2);
|
||||||
|
dbus_message_iter_append_basic(iter + 2, 's', &urgency);
|
||||||
|
dbus_message_iter_open_container(iter + 2, 'v', "y", iter + 3);
|
||||||
|
dbus_message_iter_append_basic(iter + 3, 'y', &level);
|
||||||
|
dbus_message_iter_close_container(iter + 2, iter + 3);
|
||||||
|
dbus_message_iter_close_container(iter + 1, iter + 2);
|
||||||
|
dbus_message_iter_close_container(iter, iter + 1);
|
||||||
|
dbus_message_iter_append_basic(iter, 'i', &timeout);
|
||||||
|
dbus_connection_send(connection, message, 0);
|
||||||
|
dbus_connection_flush(connection);
|
||||||
|
dbus_message_unref(message);
|
||||||
|
dbus_connection_unref(connection);
|
||||||
|
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void notify(enum dbus_level level, char const * const summary, int timeout, char const * const body)
|
||||||
|
{
|
||||||
|
send_to_dbus("dialog-information", "urgency", level, summary, body, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((format(printf, 4, 5))) static void notifyf(
|
||||||
|
enum dbus_level level, char const * const summary, int timeout, char const * const body_fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
|
va_start(ap, body_fmt);
|
||||||
|
if (vsnprintf(buf, sizeof(buf), body_fmt, ap) > 0)
|
||||||
|
{
|
||||||
|
notify(level, summary, timeout, buf);
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t get_value_index(char const * const possible_values[],
|
||||||
|
size_t possible_values_size,
|
||||||
|
char const * const needle,
|
||||||
|
size_t needle_len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < possible_values_size; ++i)
|
||||||
|
{
|
||||||
|
if (strncmp(needle, possible_values[i], needle_len) == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == possible_values_size)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_value(char const * const possible_values[],
|
||||||
|
size_t possible_values_size,
|
||||||
|
char const * const needle,
|
||||||
|
size_t needle_len)
|
||||||
|
{
|
||||||
|
if (get_value_index(possible_values, possible_values_size, needle, needle_len) == -1)
|
||||||
|
{
|
||||||
|
notifyf(DBUS_CRITICAL, "nDPIsrvd-notifyd", 5000, "BUG: Unknown value: %.*s", (int)needle_len, needle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum nDPIsrvd_callback_return notifyd_json_callback(struct nDPIsrvd_socket * const sock,
|
||||||
|
struct nDPIsrvd_instance * const instance,
|
||||||
|
struct nDPIsrvd_thread_data * const thread_data,
|
||||||
|
struct nDPIsrvd_flow * const flow)
|
||||||
|
{
|
||||||
|
(void)instance;
|
||||||
|
(void)thread_data;
|
||||||
|
|
||||||
|
struct nDPIsrvd_json_token const * const flow_event_name = TOKEN_GET_SZ(sock, "flow_event_name");
|
||||||
|
struct flow_user_data * flow_user_data = NULL;
|
||||||
|
|
||||||
|
if (flow != NULL)
|
||||||
|
{
|
||||||
|
flow_user_data = (struct flow_user_data *)flow->flow_user_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOKEN_VALUE_EQUALS_SZ(sock, flow_event_name, "detected") != 0 ||
|
||||||
|
TOKEN_VALUE_EQUALS_SZ(sock, flow_event_name, "detection-update") != 0 ||
|
||||||
|
TOKEN_VALUE_EQUALS_SZ(sock, flow_event_name, "update") != 0)
|
||||||
|
{
|
||||||
|
struct nDPIsrvd_json_token const * const flow_risks = TOKEN_GET_SZ(sock, "ndpi", "flow_risk");
|
||||||
|
struct nDPIsrvd_json_token const * current = NULL;
|
||||||
|
int next_child_index = -1, desired_severity_found = 0;
|
||||||
|
UT_string risks;
|
||||||
|
|
||||||
|
utstring_init(&risks);
|
||||||
|
|
||||||
|
if (flow_risks != NULL)
|
||||||
|
{
|
||||||
|
while ((current = nDPIsrvd_get_next_token(sock, flow_risks, &next_child_index)) != NULL)
|
||||||
|
{
|
||||||
|
nDPIsrvd_ull numeric_risk_value = (nDPIsrvd_ull)-1;
|
||||||
|
size_t flow_risk_key_len = 0;
|
||||||
|
char const * const flow_risk_key = TOKEN_GET_KEY(sock, current, &flow_risk_key_len);
|
||||||
|
|
||||||
|
if (flow_risk_key == NULL || flow_risk_key_len == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str_value_to_ull(flow_risk_key, &numeric_risk_value) == CONVERSION_OK && flow_user_data != NULL &&
|
||||||
|
(flow_user_data->detected_risks & (1ull << numeric_risk_value)) == 0)
|
||||||
|
{
|
||||||
|
flow_user_data->detected_risks |= (1ull << (numeric_risk_value - 1));
|
||||||
|
|
||||||
|
char flow_risk_sz[flow_risk_key_len + 1];
|
||||||
|
snprintf(flow_risk_sz, sizeof(flow_risk_sz), "%llu", numeric_risk_value);
|
||||||
|
size_t flow_risk_len = 0;
|
||||||
|
size_t flow_severity_len = 0;
|
||||||
|
char const * const flow_risk_str =
|
||||||
|
TOKEN_GET_VALUE(sock,
|
||||||
|
TOKEN_GET_SZ(sock, "ndpi", "flow_risk", flow_risk_sz, "risk"),
|
||||||
|
&flow_risk_len);
|
||||||
|
char const * const flow_severity_str =
|
||||||
|
TOKEN_GET_VALUE(sock,
|
||||||
|
TOKEN_GET_SZ(sock, "ndpi", "flow_risk", flow_risk_sz, "severity"),
|
||||||
|
&flow_severity_len);
|
||||||
|
|
||||||
|
if (flow_risk_str == NULL || flow_risk_len == 0 || flow_severity_str == NULL ||
|
||||||
|
flow_severity_len == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t severity_index = get_value_index(flow_severities,
|
||||||
|
nDPIsrvd_ARRAY_LENGTH(flow_severities),
|
||||||
|
flow_severity_str,
|
||||||
|
flow_severity_len);
|
||||||
|
if (severity_index != -1 && desired_flow_severities[severity_index] != 0)
|
||||||
|
{
|
||||||
|
desired_severity_found = 1;
|
||||||
|
}
|
||||||
|
utstring_printf(&risks,
|
||||||
|
"Risk: '%.*s'\n"
|
||||||
|
"Severity: '%.*s'\n",
|
||||||
|
(int)flow_risk_len,
|
||||||
|
flow_risk_str,
|
||||||
|
(int)flow_severity_len,
|
||||||
|
flow_severity_str);
|
||||||
|
check_value(flow_severities,
|
||||||
|
nDPIsrvd_ARRAY_LENGTH(flow_severities),
|
||||||
|
flow_severity_str,
|
||||||
|
flow_severity_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t flow_srcip_len = 0;
|
||||||
|
size_t flow_dstip_len = 0;
|
||||||
|
size_t flow_breed_len = 0;
|
||||||
|
size_t flow_category_len = 0;
|
||||||
|
size_t flow_hostname_len = 0;
|
||||||
|
|
||||||
|
char const * const flow_srcip = TOKEN_GET_VALUE(sock, TOKEN_GET_SZ(sock, "src_ip"), &flow_srcip_len);
|
||||||
|
char const * const flow_dstip = TOKEN_GET_VALUE(sock, TOKEN_GET_SZ(sock, "dst_ip"), &flow_dstip_len);
|
||||||
|
char const * const flow_breed_str =
|
||||||
|
TOKEN_GET_VALUE(sock, TOKEN_GET_SZ(sock, "ndpi", "breed"), &flow_breed_len);
|
||||||
|
char const * const flow_category_str =
|
||||||
|
TOKEN_GET_VALUE(sock, TOKEN_GET_SZ(sock, "ndpi", "category"), &flow_category_len);
|
||||||
|
char const * const flow_hostname =
|
||||||
|
TOKEN_GET_VALUE(sock, TOKEN_GET_SZ(sock, "ndpi", "hostname"), &flow_hostname_len);
|
||||||
|
|
||||||
|
if (flow_breed_str != NULL && flow_breed_len != 0 && flow_category_str != NULL && flow_category_len != 0)
|
||||||
|
{
|
||||||
|
ssize_t breed_index =
|
||||||
|
get_value_index(flow_breeds, nDPIsrvd_ARRAY_LENGTH(flow_breeds), flow_breed_str, flow_breed_len);
|
||||||
|
ssize_t category_index = get_value_index(flow_categories,
|
||||||
|
nDPIsrvd_ARRAY_LENGTH(flow_categories),
|
||||||
|
flow_category_str,
|
||||||
|
flow_category_len);
|
||||||
|
|
||||||
|
if ((breed_index != -1 && desired_flow_breeds[breed_index] != 0) ||
|
||||||
|
(category_index != -1 && desired_flow_categories[category_index] != 0) ||
|
||||||
|
desired_severity_found != 0)
|
||||||
|
{
|
||||||
|
notifyf(DBUS_CRITICAL,
|
||||||
|
"Flow Notification",
|
||||||
|
5000,
|
||||||
|
"%.*s -> %.*s (%.*s)\nBreed: '%.*s', Category: '%.*s'\n%s",
|
||||||
|
(int)flow_srcip_len,
|
||||||
|
flow_srcip,
|
||||||
|
(int)flow_dstip_len,
|
||||||
|
flow_dstip,
|
||||||
|
(flow_hostname_len > 0 ? (int)flow_hostname_len : 1),
|
||||||
|
(flow_hostname_len > 0 ? flow_hostname : "-"),
|
||||||
|
(int)flow_breed_len,
|
||||||
|
flow_breed_str,
|
||||||
|
(int)flow_category_len,
|
||||||
|
flow_category_str,
|
||||||
|
(utstring_len(&risks) > 0 ? utstring_body(&risks) : "No flow risks detected\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
check_value(flow_breeds, nDPIsrvd_ARRAY_LENGTH(flow_breeds), flow_breed_str, flow_breed_len);
|
||||||
|
check_value(flow_categories,
|
||||||
|
nDPIsrvd_ARRAY_LENGTH(flow_categories),
|
||||||
|
flow_category_str,
|
||||||
|
flow_category_len);
|
||||||
|
}
|
||||||
|
else if (desired_severity_found != 0)
|
||||||
|
{
|
||||||
|
notifyf(DBUS_CRITICAL,
|
||||||
|
"Risky Flow",
|
||||||
|
5000,
|
||||||
|
"%.*s -> %.*s (%.*s)\n%s",
|
||||||
|
(int)flow_srcip_len,
|
||||||
|
flow_srcip,
|
||||||
|
(int)flow_dstip_len,
|
||||||
|
flow_dstip,
|
||||||
|
(flow_hostname_len > 0 ? (int)flow_hostname_len : 1),
|
||||||
|
(flow_hostname_len > 0 ? flow_hostname : "-"),
|
||||||
|
utstring_body(&risks));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
utstring_done(&risks);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CALLBACK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_usage(char const * const arg0)
|
||||||
|
{
|
||||||
|
static char const usage[] =
|
||||||
|
"Usage: %s "
|
||||||
|
"[-s host] [-C category...] [-B breed...] [-S severity...]\n\n"
|
||||||
|
"\t-s\tDestination where nDPIsrvd is listening on.\n"
|
||||||
|
"\t-C\tDesired nDPI category which fires a notificiation.\n"
|
||||||
|
"\t \tCan be specified multiple times.\n"
|
||||||
|
"\t-B\tDesired nDPI breed which fires a notification.\n"
|
||||||
|
"\t \tCan be specified multiple times.\n"
|
||||||
|
"\t-S\tDesired nDPI risk severity which fires a notification.\n"
|
||||||
|
"\t \tCan be specified multiple times.\n"
|
||||||
|
"\n"
|
||||||
|
"Possible values for `-C': %s\n"
|
||||||
|
"Possible values for `-B': %s\n"
|
||||||
|
"Possible values for `-S': %s\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
UT_string flow_categories_str, flow_breeds_str, flow_severities_str;
|
||||||
|
utstring_init(&flow_categories_str);
|
||||||
|
utstring_init(&flow_breeds_str);
|
||||||
|
utstring_init(&flow_severities_str);
|
||||||
|
for (size_t i = 0; i < nDPIsrvd_ARRAY_LENGTH(flow_categories); ++i)
|
||||||
|
{
|
||||||
|
utstring_printf(&flow_categories_str, "%s, ", flow_categories[i]);
|
||||||
|
}
|
||||||
|
flow_categories_str.d[flow_categories_str.i - 2] = '\0';
|
||||||
|
for (size_t i = 0; i < nDPIsrvd_ARRAY_LENGTH(flow_breeds); ++i)
|
||||||
|
{
|
||||||
|
utstring_printf(&flow_breeds_str, "%s, ", flow_breeds[i]);
|
||||||
|
}
|
||||||
|
flow_breeds_str.d[flow_breeds_str.i - 2] = '\0';
|
||||||
|
for (size_t i = 0; i < nDPIsrvd_ARRAY_LENGTH(flow_severities); ++i)
|
||||||
|
{
|
||||||
|
utstring_printf(&flow_severities_str, "%s, ", flow_severities[i]);
|
||||||
|
}
|
||||||
|
flow_severities_str.d[flow_severities_str.i - 2] = '\0';
|
||||||
|
fprintf(stderr,
|
||||||
|
usage,
|
||||||
|
arg0,
|
||||||
|
utstring_body(&flow_categories_str),
|
||||||
|
utstring_body(&flow_breeds_str),
|
||||||
|
utstring_body(&flow_severities_str));
|
||||||
|
utstring_done(&flow_severities_str);
|
||||||
|
utstring_done(&flow_breeds_str);
|
||||||
|
utstring_done(&flow_categories_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_defaults(void)
|
||||||
|
{
|
||||||
|
char const * const default_severities[] = {"High", "Severe", "Critical", "Emergency"};
|
||||||
|
char const * const default_breeds[] = {"Unsafe", "Potentially_Dangerous", "Dangerous", "Unrated"};
|
||||||
|
char const * const default_categories[] = {"Mining", "Malware", "Banned_Site", "Crypto_Currency"};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nDPIsrvd_ARRAY_LENGTH(default_severities); ++i)
|
||||||
|
{
|
||||||
|
ssize_t index = get_value_index(flow_severities,
|
||||||
|
nDPIsrvd_ARRAY_LENGTH(flow_severities),
|
||||||
|
default_severities[i],
|
||||||
|
strlen(default_severities[i]));
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
desired_flow_severities[index] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nDPIsrvd_ARRAY_LENGTH(default_breeds); ++i)
|
||||||
|
{
|
||||||
|
ssize_t index = get_value_index(flow_breeds,
|
||||||
|
nDPIsrvd_ARRAY_LENGTH(flow_breeds),
|
||||||
|
default_breeds[i],
|
||||||
|
strlen(default_breeds[i]));
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
desired_flow_breeds[index] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < nDPIsrvd_ARRAY_LENGTH(default_categories); ++i)
|
||||||
|
{
|
||||||
|
ssize_t index = get_value_index(flow_categories,
|
||||||
|
nDPIsrvd_ARRAY_LENGTH(flow_categories),
|
||||||
|
default_categories[i],
|
||||||
|
strlen(default_categories[i]));
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
desired_flow_categories[index] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_options(int argc, char ** argv, struct nDPIsrvd_socket * const sock)
|
||||||
|
{
|
||||||
|
int opt, force_defaults = 1;
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "hldp:s:C:B:S:")) != -1)
|
||||||
|
{
|
||||||
|
switch (opt)
|
||||||
|
{
|
||||||
|
case 'd':
|
||||||
|
daemonize_enable();
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
free(pidfile);
|
||||||
|
pidfile = strdup(optarg);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
free(serv_optarg);
|
||||||
|
serv_optarg = strdup(optarg);
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
{
|
||||||
|
ssize_t index =
|
||||||
|
get_value_index(flow_categories, nDPIsrvd_ARRAY_LENGTH(flow_categories), optarg, strlen(optarg));
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Invalid argument for `-C': %s\n", optarg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
desired_flow_categories[index] = 1;
|
||||||
|
}
|
||||||
|
force_defaults = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'B':
|
||||||
|
{
|
||||||
|
ssize_t index =
|
||||||
|
get_value_index(flow_breeds, nDPIsrvd_ARRAY_LENGTH(flow_breeds), optarg, strlen(optarg));
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Invalid argument for `-B': %s\n", optarg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
desired_flow_breeds[index] = 1;
|
||||||
|
}
|
||||||
|
force_defaults = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'S':
|
||||||
|
{
|
||||||
|
ssize_t index =
|
||||||
|
get_value_index(flow_severities, nDPIsrvd_ARRAY_LENGTH(flow_severities), optarg, strlen(optarg));
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Invalid argument for `-S': %s\n", optarg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
desired_flow_severities[index] = 1;
|
||||||
|
}
|
||||||
|
force_defaults = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
print_usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force_defaults != 0 && set_defaults() != 0)
|
||||||
|
{
|
||||||
|
notifyf(DBUS_CRITICAL, "nDPIsrvd-notifyd", 5000, "%s\n", "BUG: Could not set default values.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serv_optarg == NULL)
|
||||||
|
{
|
||||||
|
serv_optarg = strdup(DISTRIBUTOR_UNIX_SOCKET);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nDPIsrvd_setup_address(&sock->address, serv_optarg) != 0)
|
||||||
|
{
|
||||||
|
notifyf(DBUS_CRITICAL, "nDPIsrvd-notifyd", 3000, "Could not parse address `%s'\n", serv_optarg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind < argc)
|
||||||
|
{
|
||||||
|
notifyf(DBUS_CRITICAL, "nDPIsrvd-notifyd", 3000, "%s\n", "Unexpected argument after options");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sighandler(int signum)
|
||||||
|
{
|
||||||
|
switch (signum)
|
||||||
|
{
|
||||||
|
case SIGINT:
|
||||||
|
notify(DBUS_LOW, "nDPIsrvd-notifyd", 3000, "Received SIGINT, shutdown.");
|
||||||
|
break;
|
||||||
|
case SIGTERM:
|
||||||
|
notify(DBUS_LOW, "nDPIsrvd-notifyd", 3000, "Received SIGTERM, shutdown.");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
notify(DBUS_LOW, "nDPIsrvd-notifyd", 3000, "Received unknown signal, shutdown.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
main_thread_shutdown++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
signal(SIGINT, sighandler);
|
||||||
|
signal(SIGTERM, sighandler);
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
|
struct nDPIsrvd_socket * sock =
|
||||||
|
nDPIsrvd_socket_init(0, 0, 0, sizeof(struct flow_user_data), notifyd_json_callback, NULL, NULL);
|
||||||
|
if (sock == NULL)
|
||||||
|
{
|
||||||
|
notifyf(DBUS_CRITICAL, "nDPIsrvd-notifyd", 5000, "%s\n", "BUG: nDPIsrvd socket memory allocation failed!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse_options(argc, argv, sock) != 0)
|
||||||
|
{
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daemonize_with_pidfile(pidfile) != 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int previous_connect_succeeded = 1;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (nDPIsrvd_connect(sock) != CONNECT_OK)
|
||||||
|
{
|
||||||
|
if (main_thread_shutdown != 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (previous_connect_succeeded != 0)
|
||||||
|
{
|
||||||
|
notifyf(
|
||||||
|
DBUS_CRITICAL, "nDPIsrvd-notifyd", 3000, "nDPIsrvd socket connect to %s failed!\n", serv_optarg);
|
||||||
|
previous_connect_succeeded = 0;
|
||||||
|
}
|
||||||
|
nDPIsrvd_socket_close(sock);
|
||||||
|
sleep(SLEEP_TIME_IN_S);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
previous_connect_succeeded = 1;
|
||||||
|
|
||||||
|
if (nDPIsrvd_set_read_timeout(sock, 3, 0) != 0)
|
||||||
|
{
|
||||||
|
notifyf(DBUS_CRITICAL, "nDPIsrvd-notifyd", 3000, "nDPIsrvd set read timeout failed: %s\n", strerror(errno));
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyf(DBUS_NORMAL, "nDPIsrvd-notifyd", 3000, "Connected to '%s'\n", serv_optarg);
|
||||||
|
|
||||||
|
while (main_thread_shutdown == 0)
|
||||||
|
{
|
||||||
|
enum nDPIsrvd_read_return read_ret = nDPIsrvd_read(sock);
|
||||||
|
if (errno == EINTR)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (read_ret == READ_TIMEOUT)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (read_ret != READ_OK)
|
||||||
|
{
|
||||||
|
notifyf(DBUS_CRITICAL, "nDPIsrvd-notifyd", 3000, "nDPIsrvd socket read from %s failed!\n", serv_optarg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum nDPIsrvd_parse_return parse_ret = nDPIsrvd_parse_all(sock);
|
||||||
|
if (parse_ret != PARSE_NEED_MORE_DATA)
|
||||||
|
{
|
||||||
|
notifyf(DBUS_CRITICAL,
|
||||||
|
"nDPIsrvd-notifyd",
|
||||||
|
3000,
|
||||||
|
"Could not parse JSON message %s: %.*s\n",
|
||||||
|
nDPIsrvd_enum_to_string(parse_ret),
|
||||||
|
nDPIsrvd_json_buffer_length(sock),
|
||||||
|
nDPIsrvd_json_buffer_string(sock));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nDPIsrvd_socket_close(sock);
|
||||||
|
notifyf(DBUS_NORMAL, "nDPIsrvd-notifyd", 3000, "Disconnected from '%s'.\n", serv_optarg);
|
||||||
|
if (main_thread_shutdown == 0)
|
||||||
|
{
|
||||||
|
sleep(SLEEP_TIME_IN_S);
|
||||||
|
}
|
||||||
|
} while (main_thread_shutdown == 0);
|
||||||
|
|
||||||
|
failure:
|
||||||
|
nDPIsrvd_socket_free(&sock);
|
||||||
|
daemonize_shutdown(pidfile);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
273
examples/c-simple/c-simple.c
Normal file
273
examples/c-simple/c-simple.c
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "nDPIsrvd.h"
|
||||||
|
|
||||||
|
static int main_thread_shutdown = 0;
|
||||||
|
static struct nDPIsrvd_socket * sock = NULL;
|
||||||
|
|
||||||
|
#ifdef ENABLE_MEMORY_PROFILING
|
||||||
|
void nDPIsrvd_memprof_log_alloc(size_t alloc_size)
|
||||||
|
{
|
||||||
|
(void)alloc_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nDPIsrvd_memprof_log_free(size_t free_size)
|
||||||
|
{
|
||||||
|
(void)free_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nDPIsrvd_memprof_log(char const * const format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
fprintf(stderr, "%s", "nDPIsrvd MemoryProfiler: ");
|
||||||
|
vfprintf(stderr, format, ap);
|
||||||
|
fprintf(stderr, "%s\n", "");
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void nDPIsrvd_write_flow_info_cb(struct nDPIsrvd_socket const * sock,
|
||||||
|
struct nDPIsrvd_instance const * instance,
|
||||||
|
struct nDPIsrvd_thread_data const * thread_data,
|
||||||
|
struct nDPIsrvd_flow const * flow,
|
||||||
|
void * user_data)
|
||||||
|
{
|
||||||
|
(void)sock;
|
||||||
|
(void)instance;
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"[Thread %2d][Flow %5llu][ptr: "
|
||||||
|
#ifdef __LP64__
|
||||||
|
"0x%016llx"
|
||||||
|
#else
|
||||||
|
"0x%08lx"
|
||||||
|
#endif
|
||||||
|
"][last-seen: %13llu][idle-time: %7llu][time-until-timeout: %7llu]\n",
|
||||||
|
flow->thread_id,
|
||||||
|
flow->id_as_ull,
|
||||||
|
#ifdef __LP64__
|
||||||
|
(unsigned long long int)flow,
|
||||||
|
#else
|
||||||
|
(unsigned long int)flow,
|
||||||
|
#endif
|
||||||
|
flow->last_seen,
|
||||||
|
flow->idle_time,
|
||||||
|
(thread_data != NULL && flow->last_seen + flow->idle_time >= thread_data->most_recent_flow_time
|
||||||
|
? flow->last_seen + flow->idle_time - thread_data->most_recent_flow_time
|
||||||
|
: 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nDPIsrvd_verify_flows_cb(struct nDPIsrvd_thread_data const * const thread_data,
|
||||||
|
struct nDPIsrvd_flow const * const flow,
|
||||||
|
void * user_data)
|
||||||
|
{
|
||||||
|
(void)user_data;
|
||||||
|
|
||||||
|
if (thread_data != NULL)
|
||||||
|
{
|
||||||
|
if (flow->last_seen + flow->idle_time >= thread_data->most_recent_flow_time)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Thread %d / %d, Flow %llu verification failed\n",
|
||||||
|
thread_data->thread_key,
|
||||||
|
flow->thread_id,
|
||||||
|
flow->id_as_ull);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Thread %d / %d, Flow %llu verification failed, diff: %llu\n",
|
||||||
|
thread_data->thread_key,
|
||||||
|
flow->thread_id,
|
||||||
|
flow->id_as_ull,
|
||||||
|
thread_data->most_recent_flow_time - flow->last_seen + flow->idle_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Thread [UNKNOWN], Flow %llu verification failed\n", flow->id_as_ull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sighandler(int signum)
|
||||||
|
{
|
||||||
|
struct nDPIsrvd_instance * current_instance;
|
||||||
|
struct nDPIsrvd_instance * itmp;
|
||||||
|
int verification_failed = 0;
|
||||||
|
|
||||||
|
if (signum == SIGUSR1)
|
||||||
|
{
|
||||||
|
nDPIsrvd_flow_info(sock, nDPIsrvd_write_flow_info_cb, NULL);
|
||||||
|
|
||||||
|
HASH_ITER(hh, sock->instance_table, current_instance, itmp)
|
||||||
|
{
|
||||||
|
if (nDPIsrvd_verify_flows(current_instance, nDPIsrvd_verify_flows_cb, NULL) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Flow verification failed for instance %d\n", current_instance->alias_source_key);
|
||||||
|
verification_failed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verification_failed == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", "Flow verification succeeded.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FATAL! */
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (main_thread_shutdown == 0)
|
||||||
|
{
|
||||||
|
main_thread_shutdown = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum nDPIsrvd_callback_return simple_json_callback(struct nDPIsrvd_socket * const sock,
|
||||||
|
struct nDPIsrvd_instance * const instance,
|
||||||
|
struct nDPIsrvd_thread_data * const thread_data,
|
||||||
|
struct nDPIsrvd_flow * const flow)
|
||||||
|
{
|
||||||
|
(void)sock;
|
||||||
|
(void)thread_data;
|
||||||
|
|
||||||
|
if (flow == NULL)
|
||||||
|
{
|
||||||
|
return CALLBACK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nDPIsrvd_json_token const * const alias = TOKEN_GET_SZ(sock, "alias");
|
||||||
|
struct nDPIsrvd_json_token const * const source = TOKEN_GET_SZ(sock, "source");
|
||||||
|
if (alias == NULL || source == NULL)
|
||||||
|
{
|
||||||
|
return CALLBACK_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nDPIsrvd_json_token const * const flow_event_name = TOKEN_GET_SZ(sock, "flow_event_name");
|
||||||
|
if (TOKEN_VALUE_EQUALS_SZ(sock, flow_event_name, "new") != 0)
|
||||||
|
{
|
||||||
|
printf("Instance %.*s/%.*s (HT-Key: 0x%x), Thread %d, Flow %llu new\n",
|
||||||
|
nDPIsrvd_get_token_size(sock, alias),
|
||||||
|
nDPIsrvd_get_token_value(sock, alias),
|
||||||
|
nDPIsrvd_get_token_size(sock, source),
|
||||||
|
nDPIsrvd_get_token_value(sock, source),
|
||||||
|
instance->alias_source_key,
|
||||||
|
flow->thread_id,
|
||||||
|
flow->id_as_ull);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CALLBACK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simple_flow_cleanup_callback(struct nDPIsrvd_socket * const sock,
|
||||||
|
struct nDPIsrvd_instance * const instance,
|
||||||
|
struct nDPIsrvd_thread_data * const thread_data,
|
||||||
|
struct nDPIsrvd_flow * const flow,
|
||||||
|
enum nDPIsrvd_cleanup_reason reason)
|
||||||
|
{
|
||||||
|
(void)sock;
|
||||||
|
(void)thread_data;
|
||||||
|
|
||||||
|
struct nDPIsrvd_json_token const * const alias = TOKEN_GET_SZ(sock, "alias");
|
||||||
|
struct nDPIsrvd_json_token const * const source = TOKEN_GET_SZ(sock, "source");
|
||||||
|
if (alias == NULL || source == NULL)
|
||||||
|
{
|
||||||
|
/* FATAL! */
|
||||||
|
fprintf(stderr, "BUG: Missing JSON token alias/source.\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char const * const reason_str = nDPIsrvd_enum_to_string(reason);
|
||||||
|
printf("Instance %.*s/%.*s (HT-Key: 0x%x), Thread %d, Flow %llu cleanup, reason: %s\n",
|
||||||
|
nDPIsrvd_get_token_size(sock, alias),
|
||||||
|
nDPIsrvd_get_token_value(sock, alias),
|
||||||
|
nDPIsrvd_get_token_size(sock, source),
|
||||||
|
nDPIsrvd_get_token_value(sock, source),
|
||||||
|
instance->alias_source_key,
|
||||||
|
flow->thread_id,
|
||||||
|
flow->id_as_ull,
|
||||||
|
(reason_str != NULL ? reason_str : "UNKNOWN"));
|
||||||
|
|
||||||
|
if (reason == CLEANUP_REASON_FLOW_TIMEOUT)
|
||||||
|
{
|
||||||
|
/* FATAL! */
|
||||||
|
fprintf(stderr, "Flow %llu timeouted.\n", flow->id_as_ull);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
signal(SIGUSR1, sighandler);
|
||||||
|
signal(SIGINT, sighandler);
|
||||||
|
signal(SIGTERM, sighandler);
|
||||||
|
signal(SIGPIPE, sighandler);
|
||||||
|
|
||||||
|
sock = nDPIsrvd_socket_init(0, 0, 0, 0, simple_json_callback, NULL, simple_flow_cleanup_callback);
|
||||||
|
if (sock == NULL)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nDPIsrvd_setup_address(&sock->address, (argc > 1 ? argv[1] : "127.0.0.1:7000")) != 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nDPIsrvd_connect(sock) != CONNECT_OK)
|
||||||
|
{
|
||||||
|
nDPIsrvd_socket_free(&sock);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nDPIsrvd_set_read_timeout(sock, 3, 0) != 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum nDPIsrvd_read_return read_ret = READ_OK;
|
||||||
|
while (main_thread_shutdown == 0)
|
||||||
|
{
|
||||||
|
read_ret = nDPIsrvd_read(sock);
|
||||||
|
if (errno == EINTR)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (read_ret == READ_TIMEOUT)
|
||||||
|
{
|
||||||
|
printf("No data received during the last %llu second(s).\n",
|
||||||
|
(long long unsigned int)sock->read_timeout.tv_sec);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (read_ret != READ_OK)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum nDPIsrvd_parse_return parse_ret = nDPIsrvd_parse_all(sock);
|
||||||
|
if (parse_ret != PARSE_NEED_MORE_DATA)
|
||||||
|
{
|
||||||
|
printf("Could not parse JSON message %s: %.*s\n",
|
||||||
|
nDPIsrvd_enum_to_string(parse_ret),
|
||||||
|
nDPIsrvd_json_buffer_length(sock),
|
||||||
|
nDPIsrvd_json_buffer_string(sock));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (main_thread_shutdown == 0 && read_ret != READ_OK)
|
||||||
|
{
|
||||||
|
printf("Parse read %s at JSON: %.*s\n",
|
||||||
|
nDPIsrvd_enum_to_string(read_ret),
|
||||||
|
nDPIsrvd_json_buffer_length(sock),
|
||||||
|
nDPIsrvd_json_buffer_string(sock));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
1
examples/cxx-graph
Submodule
1
examples/cxx-graph
Submodule
Submodule examples/cxx-graph added at 68eb1b105d
@@ -1,9 +0,0 @@
|
|||||||
module github.com/lnslbrty/nDPId/examples/go-dashboard
|
|
||||||
|
|
||||||
go 1.14
|
|
||||||
|
|
||||||
require (
|
|
||||||
ui v0.0.0-00010101000000-000000000000
|
|
||||||
)
|
|
||||||
|
|
||||||
replace ui => ./ui
|
|
||||||
@@ -1,218 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"ui"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
WarningLogger *log.Logger
|
|
||||||
InfoLogger *log.Logger
|
|
||||||
ErrorLogger *log.Logger
|
|
||||||
|
|
||||||
NETWORK_BUFFER_MAX_SIZE uint16 = 12288
|
|
||||||
NETWORK_BUFFER_LENGTH_DIGITS uint16 = 5
|
|
||||||
)
|
|
||||||
|
|
||||||
type packet_event struct {
|
|
||||||
ThreadID uint8 `json:"thread_id"`
|
|
||||||
PacketID uint64 `json:"packet_id"`
|
|
||||||
|
|
||||||
FlowID uint32 `json:"flow_id"`
|
|
||||||
FlowPacketID uint64 `json:"flow_packet_id"`
|
|
||||||
|
|
||||||
PacketEventID uint8 `json:"packet_event_id"`
|
|
||||||
PacketEventName string `json:"packet_event_name"`
|
|
||||||
PacketOversize bool `json:"pkt_oversize"`
|
|
||||||
PacketTimestampS uint64 `json:"pkt_ts_sec"`
|
|
||||||
PacketTimestampUs uint64 `json:"pkt_ts_usec"`
|
|
||||||
PacketLength uint32 `json:"pkt_len"`
|
|
||||||
PacketL4Length uint32 `json:"pkt_l4_len"`
|
|
||||||
Packet string `json:"pkt"`
|
|
||||||
PacketCaptureLength uint32 `json:"pkt_caplen"`
|
|
||||||
PacketType uint32 `json:"pkt_type"`
|
|
||||||
PacketL3Offset uint32 `json:"pkt_l3_offset"`
|
|
||||||
PacketL4Offset uint32 `json:"pkt_l4_offset"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type flow_event struct {
|
|
||||||
ThreadID uint8 `json:"thread_id"`
|
|
||||||
PacketID uint64 `json:"packet_id"`
|
|
||||||
|
|
||||||
FlowID uint32 `json:"flow_id"`
|
|
||||||
FlowPacketID uint64 `json:"flow_packet_id"`
|
|
||||||
FlowFirstSeen uint64 `json:"flow_first_seen"`
|
|
||||||
FlowLastSeen uint64 `json:"flow_last_seen"`
|
|
||||||
FlowTotalLayer4DataLength uint64 `json:"flow_tot_l4_data_len"`
|
|
||||||
FlowMinLayer4DataLength uint64 `json:"flow_min_l4_data_len"`
|
|
||||||
FlowMaxLayer4DataLength uint64 `json:"flow_max_l4_data_len"`
|
|
||||||
FlowAvgLayer4DataLength uint64 `json:"flow_avg_l4_data_len"`
|
|
||||||
FlowDatalinkLayer uint8 `json:"flow_datalink"`
|
|
||||||
MaxPackets uint8 `json:"flow_max_packets"`
|
|
||||||
IsMidstreamFlow uint32 `json:"midstream"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type basic_event struct {
|
|
||||||
ThreadID uint8 `json:"thread_id"`
|
|
||||||
PacketID uint64 `json:"packet_id"`
|
|
||||||
|
|
||||||
BasicEventID uint8 `json:"basic_event_id"`
|
|
||||||
BasicEventName string `json:"basic_event_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func processJson(jsonStr string) {
|
|
||||||
jsonMap := make(map[string]interface{})
|
|
||||||
err := json.Unmarshal([]byte(jsonStr), &jsonMap)
|
|
||||||
if err != nil {
|
|
||||||
ErrorLogger.Printf("BUG: JSON error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if jsonMap["packet_event_id"] != nil {
|
|
||||||
pe := packet_event{}
|
|
||||||
if err := json.Unmarshal([]byte(jsonStr), &pe); err != nil {
|
|
||||||
ErrorLogger.Printf("BUG: JSON Unmarshal error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
InfoLogger.Printf("PACKET EVENT %v\n", pe)
|
|
||||||
} else if jsonMap["flow_event_id"] != nil {
|
|
||||||
fe := flow_event{}
|
|
||||||
if err := json.Unmarshal([]byte(jsonStr), &fe); err != nil {
|
|
||||||
ErrorLogger.Printf("BUG: JSON Unmarshal error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
InfoLogger.Printf("FLOW EVENT %v\n", fe)
|
|
||||||
} else if jsonMap["basic_event_id"] != nil {
|
|
||||||
be := basic_event{}
|
|
||||||
if err := json.Unmarshal([]byte(jsonStr), &be); err != nil {
|
|
||||||
ErrorLogger.Printf("BUG: JSON Unmarshal error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
InfoLogger.Printf("BASIC EVENT %v\n", be)
|
|
||||||
} else {
|
|
||||||
ErrorLogger.Printf("BUG: Unknown JSON: %v\n", jsonStr)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
//InfoLogger.Printf("JSON map: %v\n-------------------------------------------------------\n", jsonMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
func eventHandler(ui *ui.Tui, wdgts *ui.Widgets, reader chan string) {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ui.MainTicker.C:
|
|
||||||
if err := wdgts.RawJson.Write(fmt.Sprintf("%s\n", "--- HEARTBEAT ---")); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-ui.Context.Done():
|
|
||||||
return
|
|
||||||
|
|
||||||
case jsonStr := <-reader:
|
|
||||||
if err := wdgts.RawJson.Write(fmt.Sprintf("%s\n", jsonStr)); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
InfoLogger = log.New(os.Stderr, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
|
|
||||||
WarningLogger = log.New(os.Stderr, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile)
|
|
||||||
ErrorLogger = log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
|
|
||||||
|
|
||||||
writer := make(chan string, 256)
|
|
||||||
|
|
||||||
go func(writer chan string) {
|
|
||||||
con, err := net.Dial("tcp", "127.0.0.1:7000")
|
|
||||||
if err != nil {
|
|
||||||
ErrorLogger.Printf("Connection failed: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := make([]byte, NETWORK_BUFFER_MAX_SIZE)
|
|
||||||
jsonStr := string("")
|
|
||||||
jsonStrLen := uint16(0)
|
|
||||||
jsonLen := uint16(0)
|
|
||||||
brd := bufio.NewReaderSize(con, int(NETWORK_BUFFER_MAX_SIZE))
|
|
||||||
|
|
||||||
for {
|
|
||||||
nread, err := brd.Read(buf)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if err != io.EOF {
|
|
||||||
ErrorLogger.Printf("Read Error: %v\n", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if nread == 0 || err == io.EOF {
|
|
||||||
WarningLogger.Printf("Disconnect from Server\n")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonStr += string(buf[:nread])
|
|
||||||
jsonStrLen += uint16(nread)
|
|
||||||
|
|
||||||
for {
|
|
||||||
if jsonStrLen < NETWORK_BUFFER_LENGTH_DIGITS+1 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if jsonStr[NETWORK_BUFFER_LENGTH_DIGITS] != '{' {
|
|
||||||
ErrorLogger.Printf("BUG: JSON invalid opening character at position %d: '%s' (%x)\n",
|
|
||||||
NETWORK_BUFFER_LENGTH_DIGITS,
|
|
||||||
string(jsonStr[:NETWORK_BUFFER_LENGTH_DIGITS]), jsonStr[NETWORK_BUFFER_LENGTH_DIGITS])
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if jsonLen == 0 {
|
|
||||||
var tmp uint64
|
|
||||||
if tmp, err = strconv.ParseUint(strings.TrimLeft(jsonStr[:NETWORK_BUFFER_LENGTH_DIGITS], "0"), 10, 16); err != nil {
|
|
||||||
ErrorLogger.Printf("BUG: Could not parse length of a JSON string: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
|
||||||
jsonLen = uint16(tmp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if jsonStrLen < jsonLen+NETWORK_BUFFER_LENGTH_DIGITS {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if jsonStr[jsonLen+NETWORK_BUFFER_LENGTH_DIGITS-2] != '}' || jsonStr[jsonLen+NETWORK_BUFFER_LENGTH_DIGITS-1] != '\n' {
|
|
||||||
ErrorLogger.Printf("BUG: JSON invalid closing character at position %d: '%s'\n",
|
|
||||||
jsonLen+NETWORK_BUFFER_LENGTH_DIGITS,
|
|
||||||
string(jsonStr[jsonLen+NETWORK_BUFFER_LENGTH_DIGITS-1]))
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
writer <- jsonStr[NETWORK_BUFFER_LENGTH_DIGITS : NETWORK_BUFFER_LENGTH_DIGITS+jsonLen]
|
|
||||||
|
|
||||||
jsonStr = jsonStr[jsonLen+NETWORK_BUFFER_LENGTH_DIGITS:]
|
|
||||||
jsonStrLen -= (jsonLen + NETWORK_BUFFER_LENGTH_DIGITS)
|
|
||||||
jsonLen = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}(writer)
|
|
||||||
|
|
||||||
tui, wdgts := ui.Init()
|
|
||||||
go eventHandler(tui, wdgts, writer)
|
|
||||||
ui.Run(tui)
|
|
||||||
|
|
||||||
/*
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case _ = <-writer:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
module github.com/lnslbrty/nDPId/examples/go-dashboard/ui
|
|
||||||
|
|
||||||
go 1.14
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/mum4k/termdash v0.12.3-0.20200901030524-fe3e97353191
|
|
||||||
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 // indirect
|
|
||||||
)
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/mum4k/termdash"
|
|
||||||
"github.com/mum4k/termdash/container"
|
|
||||||
"github.com/mum4k/termdash/keyboard"
|
|
||||||
"github.com/mum4k/termdash/linestyle"
|
|
||||||
"github.com/mum4k/termdash/terminal/termbox"
|
|
||||||
"github.com/mum4k/termdash/terminal/terminalapi"
|
|
||||||
"github.com/mum4k/termdash/widgets/text"
|
|
||||||
)
|
|
||||||
|
|
||||||
const rootID = "root"
|
|
||||||
const redrawInterval = 250 * time.Millisecond
|
|
||||||
|
|
||||||
type Tui struct {
|
|
||||||
Term terminalapi.Terminal
|
|
||||||
Context context.Context
|
|
||||||
Cancel context.CancelFunc
|
|
||||||
Container *container.Container
|
|
||||||
MainTicker *time.Ticker
|
|
||||||
}
|
|
||||||
|
|
||||||
type Widgets struct {
|
|
||||||
Menu *text.Text
|
|
||||||
RawJson *text.Text
|
|
||||||
}
|
|
||||||
|
|
||||||
func newWidgets(ctx context.Context) (*Widgets, error) {
|
|
||||||
menu, err := text.New()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
rawJson, err := text.New(text.RollContent(), text.WrapAtWords())
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Widgets{
|
|
||||||
Menu: menu,
|
|
||||||
RawJson: rawJson,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Init() (*Tui, *Widgets) {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
ui := Tui{}
|
|
||||||
|
|
||||||
ui.Term, err = termbox.New(termbox.ColorMode(terminalapi.ColorMode256))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.Context, ui.Cancel = context.WithCancel(context.Background())
|
|
||||||
|
|
||||||
wdgts, err := newWidgets(ui.Context)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.Container, err = container.New(ui.Term,
|
|
||||||
container.Border(linestyle.None),
|
|
||||||
container.BorderTitle("[ESC to Quit]"),
|
|
||||||
container.SplitHorizontal(
|
|
||||||
container.Top(
|
|
||||||
container.Border(linestyle.Light),
|
|
||||||
container.BorderTitle("Go nDPId Dashboard"),
|
|
||||||
container.PlaceWidget(wdgts.Menu),
|
|
||||||
),
|
|
||||||
container.Bottom(
|
|
||||||
container.Border(linestyle.Light),
|
|
||||||
container.BorderTitle("Raw JSON"),
|
|
||||||
container.PlaceWidget(wdgts.RawJson),
|
|
||||||
),
|
|
||||||
container.SplitFixed(3),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.MainTicker = time.NewTicker(1 * time.Second)
|
|
||||||
|
|
||||||
return &ui, wdgts
|
|
||||||
}
|
|
||||||
|
|
||||||
func Run(ui *Tui) {
|
|
||||||
defer ui.Term.Close()
|
|
||||||
|
|
||||||
quitter := func(k *terminalapi.Keyboard) {
|
|
||||||
if k.Key == keyboard.KeyEsc || k.Key == keyboard.KeyCtrlC {
|
|
||||||
ui.Cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := termdash.Run(ui.Context, ui.Term, ui.Container, termdash.KeyboardSubscriber(quitter), termdash.RedrawInterval(redrawInterval)); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
16
examples/go-dashboard/vendor/github.com/mattn/go-runewidth/.travis.yml
generated
vendored
16
examples/go-dashboard/vendor/github.com/mattn/go-runewidth/.travis.yml
generated
vendored
@@ -1,16 +0,0 @@
|
|||||||
language: go
|
|
||||||
sudo: false
|
|
||||||
go:
|
|
||||||
- 1.13.x
|
|
||||||
- tip
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- go get -t -v ./...
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go generate
|
|
||||||
- git diff --cached --exit-code
|
|
||||||
- ./go.test.sh
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
||||||
21
examples/go-dashboard/vendor/github.com/mattn/go-runewidth/LICENSE
generated
vendored
21
examples/go-dashboard/vendor/github.com/mattn/go-runewidth/LICENSE
generated
vendored
@@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2016 Yasuhiro Matsumoto
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
27
examples/go-dashboard/vendor/github.com/mattn/go-runewidth/README.md
generated
vendored
27
examples/go-dashboard/vendor/github.com/mattn/go-runewidth/README.md
generated
vendored
@@ -1,27 +0,0 @@
|
|||||||
go-runewidth
|
|
||||||
============
|
|
||||||
|
|
||||||
[](https://travis-ci.org/mattn/go-runewidth)
|
|
||||||
[](https://codecov.io/gh/mattn/go-runewidth)
|
|
||||||
[](http://godoc.org/github.com/mattn/go-runewidth)
|
|
||||||
[](https://goreportcard.com/report/github.com/mattn/go-runewidth)
|
|
||||||
|
|
||||||
Provides functions to get fixed width of the character or string.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
```go
|
|
||||||
runewidth.StringWidth("つのだ☆HIRO") == 12
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Author
|
|
||||||
------
|
|
||||||
|
|
||||||
Yasuhiro Matsumoto
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
under the MIT License: http://mattn.mit-license.org/2013
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user