├── .clang-format ├── .gitignore ├── CHANGELOG ├── LICENSE ├── Makefile ├── README.md ├── TODO ├── bin └── .gitkeep ├── doc ├── netproc.8 └── netproc.8.txt ├── get_version.sh ├── img └── print.png ├── obj └── .gitkeep ├── release.sh ├── src ├── bpf │ └── program.bpf ├── color.c ├── color.h ├── config.c ├── config.h ├── connection.c ├── connection.h ├── directory.c ├── directory.h ├── filter.c ├── filter.h ├── full_read.c ├── full_read.h ├── hashtable.c ├── hashtable.h ├── human_readable.c ├── human_readable.h ├── jhash.h ├── log.c ├── log.h ├── m_error.c ├── m_error.h ├── macro_util.h ├── main.c ├── packet.c ├── packet.h ├── pid.c ├── pid.h ├── processes.c ├── processes.h ├── rate.c ├── rate.h ├── resolver │ ├── domain.c │ ├── domain.h │ ├── get_cpu.c │ ├── get_cpu.h │ ├── queue.c │ ├── queue.h │ ├── resolver.c │ ├── resolver.h │ ├── service.c │ ├── service.h │ ├── sock_util.c │ ├── sock_util.h │ ├── thread_pool.c │ └── thread_pool.h ├── ring.c ├── ring.h ├── round.c ├── round.h ├── slist.h ├── sock.c ├── sock.h ├── sockaddr.h ├── sort.c ├── sort.h ├── statistics.c ├── statistics.h ├── str.c ├── str.h ├── timer.c ├── timer.h ├── translate.c ├── translate.h ├── tui.c ├── tui.h ├── usage.c ├── usage.h ├── vector.c └── vector.h └── tests ├── .gitignore ├── Makefile ├── cycle_counting.h ├── file_test_full_read.bin ├── test_full_read.c ├── test_hashtable.c ├── test_ht_conn.c ├── test_human_readable.c ├── test_packet.c ├── test_queue.c ├── test_rate.c ├── test_sec2clock.c ├── test_str.c ├── test_vector.c ├── tests_all.c ├── tick_tack.c └── unity ├── unity.c ├── unity.h └── unity_internals.h /.clang-format: -------------------------------------------------------------------------------- 1 | # clang-format version 11.0.1 2 | 3 | Language: Cpp 4 | BasedOnStyle: GNU 5 | AccessModifierOffset: -2 6 | AlignEscapedNewlines: Left 7 | AlignTrailingComments: true 8 | AlignAfterOpenBracket: Align 9 | AllowAllParametersOfDeclarationOnNextLine: false 10 | AllowAllArgumentsOnNextLine: false 11 | AllowShortFunctionsOnASingleLine: All 12 | AlwaysBreakAfterReturnType: All 13 | BinPackArguments: false 14 | BinPackParameters: false 15 | BreakBeforeBinaryOperators: None 16 | IndentWidth: 2 17 | IndentCaseLabels: true 18 | ColumnLimit: 80 19 | ContinuationIndentWidth: 8 20 | SpaceAfterCStyleCast: true 21 | SpacesInParentheses: true 22 | SpacesInCStyleCastParentheses: true 23 | SpacesBeforeTrailingComments: 2 24 | SortIncludes: false 25 | ... 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #binary 2 | bin/netproc 3 | 4 | #gdb 5 | *.gdb_history 6 | 7 | #txt 8 | *.txt 9 | 10 | #obj 11 | *.o 12 | 13 | #log 14 | *.log 15 | 16 | #vim 17 | *.swp 18 | 19 | #tarball 20 | *.tar* 21 | tags 22 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | Legend: 2 | + Added feature 3 | * Improved/changed feature 4 | - Bug fixed 5 | ! Known issue / missing feature 6 | 7 | 0.6.7 - 2025-01-11 8 | * Update README 9 | 10 | 0.6.6 - 2023-9-18 11 | - Minor fix in cleanup code. 12 | 13 | 0.6.5 - 2022-07-30 14 | - bug count of time 15 | - call to resolver_init being done unnecessarily in some cases 16 | - lost connection stats on updates 17 | * using hashtable in search of connections, by inode and tuple 18 | * improvements file log.c 19 | 20 | 0.6.3 - 2021-12-06 21 | + add new color scheme 22 | * improved timer of packets fragments 23 | * internal timer now return in milliseconds instead of seconds 24 | * moved code filter bpf to section rodata 25 | * using dinamyc vector to manage conections of processes 26 | - resolved possible buffoverflow in call readlink 27 | - fix ncurses linkage in old systems 28 | 29 | 0.6.2 - 2021-08-13 30 | - fixed link ncurses on certain systems, LDLIBS in makefile, PR #2 31 | - fixed when displaying process with long name, issue #5 32 | 33 | 0.6.0 - 2021-08-03 34 | - invalid interface argument handling 35 | - cleanup on error cases 36 | - automatic calculation of the size of the pid column 37 | - incorrect sorting 38 | - minor bug scroll horizontal 39 | * using ncursesw instead of ncurses for better support for 40 | ALTCHARSERT characters 41 | * readjusting mmap socket values, improving consumed of memory 42 | * automatic calculation size pad ncurses, improving consumed of memory 43 | * improved dns resolver, now uses thread pool and hashtable, improving the 44 | use of system recursions 45 | * using hashtable implementation in search of processes 46 | 47 | 0.5.5 - 2021-02-23 48 | - connection port number was being displayed incorrectly 49 | - fixed bug that was not translated to port for a service name, bug since 50 | version 0.3.1 51 | * show the name of the process and its arguments 52 | + implemented mode verbose, that alse show process whitout traffic 53 | + added man page 54 | 55 | 0.5.0 - 2021-02-12 56 | - bin folder not present (necessary to compilation) 57 | * header information show more fast 58 | + option -f, allows save process statistics to a file 59 | + header now reports total rate pps and total rate bps 60 | 61 | 0.4.4 - 2020-11-13 62 | + general information at the top of the screen 63 | * scroll using arrow keys 64 | 65 | 0.4.3 - 2020-09-13 66 | + simultaneous tracking of TCP and UDP protocols 67 | 68 | 0.4.2 - 2020-08-13 69 | + show interface associate with conection 70 | * improved consult dns, now no cause delay in application 71 | * improved management of memory 72 | * cpu usage, extended numbers of blocks, frames per blocks and len each 73 | frame from mmap ring 74 | * cpu usage, decreasing update frequency of processes 75 | * filter bpf, now support interface tun 76 | 77 | 0.4.1 - 2020-06-21 78 | - bug fix that close program when screen on resized 79 | 80 | 0.4.0 - 2020-06-20 81 | * improvements interface user: 82 | colors; 83 | scroll horizontal and vertial; 84 | sort by columns; 85 | * improved CPU usage using socket mmap with TPACKET_V3 and poll 86 | * traffic no necessary discarded with filter BPF 87 | * check necessary update process more eficient in mode udp 88 | - check argument '-i' improved 89 | - statistics conections storage 90 | + statistics total bytes/bits TX and RX 91 | 92 | 0.3.1 - 2020-05-25 93 | + translate of host and service 94 | * improved parse of options, now code is more readble and checking of 95 | parameters is best 96 | * updated [options] of README 97 | - minor change of function copy_conections in process.c 98 | 99 | 0.2.0 - 2020-05-22 100 | + individual statistics by connections, option '-c' 101 | * show a error when invalid argument was passed, function parte 102 | _options in main.c 103 | * changed the display layout, moved column program to last 104 | * program column width calculated "automatically" 105 | 106 | 0.1.6 - 2020-05-18 107 | - limited the maximum size to be displayed for the process name. 108 | * translated into english the help message 109 | ! IPv6 support 110 | ! individual statistics by connections 111 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # https://www.gnu.org/software/make/manual/make.html#Pattern-Examples 3 | # http://wiki.inf.ufpr.br/maziero/doku.php?id=prog2:o_sistema_make 4 | 5 | # CC compilador a ser usado 6 | # CPPFLAGS opções para o preprocessador (-DDEBUG ou -I $(DIR_INCLUDES)) 7 | # CFLAGS opções para o compilador (-std=c99) 8 | # LDFLAGS opções para o ligador (-static -L/opt/opencv/lib) 9 | # LDLIBS bibliotecas a ligar ao código gerado (-lpthreads -lmath) 10 | 11 | # https://www.gnu.org/software/make/manual/make.html#Automatic-Variables 12 | # $@ - representa o alvo 13 | # $^ - representa a lista de dependencia 14 | # $< - representa a primeira dependencia 15 | 16 | # alvo: dependencia 17 | # regra 18 | 19 | PROG_NAME=netproc 20 | 21 | prefix ?= /usr/local 22 | 23 | PATH_DOC_INSTALL=$(DESTDIR)$(prefix)/share/man/man8 24 | PATH_INSTALL=$(DESTDIR)$(prefix)/sbin 25 | 26 | SRCDIR=./src 27 | OBJDIR=./obj 28 | BINDIR=./bin 29 | DOCDIR=./doc 30 | 31 | CC ?= gcc 32 | CFLAGS += -Wall -Wextra -pedantic -Wformat=2 33 | 34 | # environment var 35 | ifdef DEBUG 36 | CFLAGS += -O0 -ggdb -fsanitize=address 37 | LDFLAGS += -fsanitize=address 38 | else ifdef DEV 39 | CFLAGS += -O0 -ggdb 40 | else 41 | CPPFLAGS += -D NDEBUG 42 | CFLAGS += -O2 -flto 43 | LDFLAGS += -s -O2 -flto 44 | endif 45 | 46 | LDLIBS=$(shell ncursesw6-config --libs 2> /dev/null) 47 | 48 | # if LDLIBS is empty 49 | ifeq ($(LDLIBS),) 50 | LDLIBS=$(shell ncursesw5-config --libs 2> /dev/null) 51 | endif 52 | 53 | LDLIBS += -lpthread 54 | 55 | #.c files all subdirectories 56 | C_SOURCE= $(wildcard $(SRCDIR)/*.c) $(wildcard $(SRCDIR)/*/*.c) 57 | 58 | # .h files all subdirectories 59 | H_SOURCE=$(wildcard $(SRCDIR)/*.h) $(wildcard $(SRCDIR)/*/*.h) 60 | 61 | # https://www.gnu.org/software/make/manual/make.html#General-Search 62 | # search path prerequisits 63 | VPATH= src src/resolver 64 | 65 | # Object files 66 | # todos arquivos .c trocado a extensão para .o 67 | # transforma 'src/foo.c' em 'obj/foo.o' 68 | OBJECTS=$(addprefix $(OBJDIR)/, $(notdir $(C_SOURCE:.c=.o) ) ) 69 | 70 | # alvos fake, não são arquivos 71 | .PHONY: all clean distclean run install uninstall format man tarball 72 | 73 | all: $(BINDIR)/$(PROG_NAME) 74 | 75 | # linka os arquivos ojetos para o executavel 76 | # regra ja é implitica dessa forma, 77 | # adicionado apenas para 'clareza' 78 | 79 | $(BINDIR)/$(PROG_NAME): $(OBJECTS) 80 | $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ 81 | 82 | # mascara generica para compilar arquivos .o 83 | # utiliza todos os arquivos headers como dependencia, 84 | # caso algum seja atualizado, todo os objetos são recompilados 85 | 86 | $(OBJDIR)/%.o: %.c $(H_SOURCE) 87 | $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ 88 | 89 | clean: 90 | @ find . -type f -name '*.o' -delete 91 | @ echo "Object files removed" 92 | 93 | distclean: clean 94 | @ find $(BINDIR) -name $(PROG_NAME) -delete 95 | @ echo "Removed "$(BINDIR)"/"$(PROG_NAME) 96 | 97 | run: 98 | sudo $(BINDIR)/$(PROG_NAME) 99 | 100 | install: 101 | @ install -d -m 755 $(PATH_INSTALL) 102 | @ install --strip $(BINDIR)/$(PROG_NAME) $(PATH_INSTALL); \ 103 | echo "Binary instaled in "$(PATH_INSTALL)"/"$(PROG_NAME) 104 | @ install -d -m 755 $(PATH_DOC_INSTALL) 105 | @ install -g 0 -o 0 -m 0644 $(DOCDIR)/$(PROG_NAME).8 $(PATH_DOC_INSTALL); \ 106 | gzip -9 -f $(PATH_DOC_INSTALL)/$(PROG_NAME).8 ; \ 107 | echo "Man page instaled in "$(PATH_DOC_INSTALL)/$(PROG_NAME)".8.gz" 108 | 109 | uninstall: 110 | @ find $(PATH_DOC_INSTALL) $(PATH_INSTALL) -type f -name "$(PROG_NAME)*" \ 111 | -delete -exec echo "Removed "{} \; 112 | 113 | format: 114 | @ echo "Formating code" 115 | @ clang-format -i $(SRCDIR)/*.[ch] 116 | @ clang-format -i $(SRCDIR)/*/*.[ch] 117 | @ clang-format -i tests/*.[ch] 118 | 119 | man: 120 | txt2man -t $(PROG_NAME) -v "$(PROG_NAME) man" -s 8 \ 121 | $(DOCDIR)/$(PROG_NAME).8.txt > $(DOCDIR)/$(PROG_NAME).8 122 | 123 | VERSION = $(shell ./get_version.sh) 124 | tarball: 125 | git archive -o "netproc-$(VERSION).tar.gz" $(VERSION) 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Netproc 2 | 3 | tool to monitor network traffic based on processes 4 | 5 | 6 | ![netproc print](img/print.png) 7 | 8 | 9 | #### Dependences 10 | [Debian based] 11 | $ sudo apt install gcc make libncurses-dev 12 | 13 | [Red Hat Based] 14 | $ sudo yum install gcc make ncurses-devel 15 | 16 | #### Install 17 | $ git clone https://github.com/berghetti/netproc.git 18 | $ cd netproc 19 | $ make 20 | $ sudo make install 21 | 22 | #### Install single command 23 | $ git clone https://github.com/berghetti/netproc.git; cd netproc; make; sudo make install 24 | 25 | #### Options / Usage 26 | Usage: netproc [options] 27 | 28 | Options: 29 | -B, --bytes view in bytes, default in bits 30 | -c visualization each active connection of the process 31 | -f, --file "filename" save statistics in file, file name is optional, 32 | default is 'netproc.log' 33 | -h, --help show this message 34 | -i, --interface iface specifies an interface, default is all 35 | (except interface with network 127.0.0.0/8) 36 | -n numeric host and service, implicit '-c', try '-nh' to no 37 | translate only host or '-np' to not translate only service 38 | -p, --protocol tcp|udp specifies a protocol, the default is tcp and udp 39 | -v, --verbose verbose mode, alse show process without traffic 40 | --si show SI format, with powers of 10, default is IEC, 41 | with powers of 2 42 | -V, --version show version 43 | 44 | when running press: 45 | arrow keys scroll 46 | s change column-based sort 47 | q exit 48 | 49 | #### Running without root 50 | $ sudo setcap "cap_net_admin,cap_net_raw+pe" /usr/local/sbin/netproc 51 | 52 | #### Uninstall 53 | $ sudo make uninstall 54 | 55 | #### Debug 56 | $ make clean 57 | $ DEBUG=1 make 58 | $ sudo ./bin/netproc 2> log.txt 59 | 60 | $ sudo DESTDIR=/tmp make install 61 | 62 | ### Netproc in Linux Distributions 63 | 64 | [![Packaging status](https://repology.org/badge/vertical-allrepos/netproc.svg)](https://repology.org/project/netproc/versions) 65 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | 2 | * use macro %pri% in functions like printf 3 | * Add support IPv6 4 | * Usage tcp_diag to get conections 5 | * make a lib netproc 6 | -------------------------------------------------------------------------------- /bin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berghetti/netproc/d6b22e19728dca1aab81442a89cf07b0574370cc/bin/.gitkeep -------------------------------------------------------------------------------- /doc/netproc.8: -------------------------------------------------------------------------------- 1 | .\" Text automatically generated by txt2man 2 | .TH netproc 8 "05 December 2021" "" "netproc man" 3 | .SH NAME 4 | \fBnetproc \fP- process-based network monitoring tool 5 | .SH SYNOPSIS 6 | .nf 7 | .fam C 8 | \fBnetproc\fP [\fB-B\fP] [\fB-c\fP] [\fB-f\fP [\fIfilename\fP]] [\fB-h\fP] [\fB-i\fP \fIiface\fP] [\fB-n\fP] [\fB-p\fP \fIudp\fP | \fItcp\fP] [\fB-v\fP] 9 | [\fB--si\fP] 10 | .fam T 11 | .fi 12 | .fam T 13 | .fi 14 | .SH DESCRIPTION 15 | \fBnetproc\fP monitors network traffic and tries to find out which process 16 | this traffic belongs to, this is useful to quickly know who is consuming 17 | our network resources. 18 | .PP 19 | \fBnetproc\fP currently supports the TCP and UDP protocols over the IPv4 protocol. 20 | .SH OPTIONS 21 | .TP 22 | .B 23 | \fB-B\fP, \fB--bytes\fP 24 | view in bytes, default in bits 25 | .TP 26 | .B 27 | \fB-c\fP 28 | visualization each active connection of the process 29 | .TP 30 | .B 31 | \fB--color\fP 1|2|3 32 | color scheme, 1 is default 33 | .TP 34 | .B 35 | \fB-f\fP, \fB--file\fP "\fIfilename\fP" 36 | save statistics in file, \fIfilename\fP is optional, 37 | default is 'netproc.log' 38 | .TP 39 | .B 40 | \fB-h\fP, \fB--help\fP 41 | show this message 42 | .TP 43 | .B 44 | \fB-i\fP, \fB--interface\fP \fIiface\fP 45 | specifies an interface, default is all 46 | (except interface with network 127.0.0.0/8) 47 | .TP 48 | .B 49 | \fB-n\fP 50 | numeric host and service, implicit '\fB-c\fP', try '\fB-nh\fP' to no 51 | translate only host or '\fB-np\fP' to not translate only service 52 | .TP 53 | .B 54 | \fB-p\fP, \fB--protocol\fP \fItcp\fP|\fIudp\fP 55 | specifies a protocol, the default is \fItcp\fP and \fIudp\fP 56 | .TP 57 | .B 58 | \fB--si\fP 59 | show SI format, with powers of 1000, default is IEC, 60 | with powers of 1024 61 | .TP 62 | .B 63 | \fB-v\fP, \fB--verbose\fP 64 | verbose mode, also show process without traffic 65 | .TP 66 | .B 67 | \fB-V\fP, \fB--version\fP 68 | show version 69 | .SH RUNNING CONTROL 70 | 71 | .TP 72 | .B 73 | arrow keys 74 | scroll 75 | .TP 76 | .B 77 | s 78 | change column-based sort 79 | .TP 80 | .B 81 | q 82 | exit 83 | .SH EXAMPLES 84 | This command will display the ips / ports of the \fIudp\fP traffic of the processes, 85 | monitoring all available interfaces, except the loopback, and log a summary 86 | in the file "log.txt": 87 | .PP 88 | .nf 89 | .fam C 90 | # netproc -p udp -c -f "log.txt" 91 | 92 | .fam T 93 | .fi 94 | Useful to monitor the file generated in the above command: 95 | .PP 96 | .nf 97 | .fam C 98 | $ watch -t -d 'cat log.txt' 99 | $ watch -t 'cut -c -$COLUMNS log.txt' 100 | 101 | .fam T 102 | .fi 103 | Running whitout root: 104 | .PP 105 | .nf 106 | .fam C 107 | $ sudo setcap "cap_net_admin,cap_net_raw+pe" /usr/local/sbin/netproc 108 | $ export PATH=$PATH:/usr/local/sbin 109 | 110 | .fam T 111 | .fi 112 | .SH BUGS 113 | Help improve this software, report bugs at 114 | .PP 115 | https://github.com/berghetti/\fBnetproc\fP/issues 116 | .SH AUTHOR 117 | Mayco Souza Berghetti 118 | .SH COPYRIGHT 119 | Copyright © 2020-2021 Mayco S. Berghetti. Licensed GPLv3+: GNU GPL version 3 or later . 120 | This is free software: you are free to change and redistribute it. 121 | There is NO WARRANTY, to the extent permitted by law. 122 | -------------------------------------------------------------------------------- /doc/netproc.8.txt: -------------------------------------------------------------------------------- 1 | NAME 2 | netproc - process-based network monitoring tool 3 | SYNOPSIS 4 | netproc [-B] [-c] [-f [filename]] [-h] [-i iface] [-n] [-p udp | tcp] [-v] 5 | [--si] 6 | DESCRIPTION 7 | netproc monitors network traffic and tries to find out which process 8 | this traffic belongs to, this is useful to quickly know who is consuming 9 | our network resources. 10 | 11 | netproc currently supports the TCP and UDP protocols over the IPv4 protocol. 12 | 13 | OPTIONS 14 | -B, --bytes view in bytes, default in bits 15 | -c visualization each active connection of the process 16 | --color 1|2|3 color scheme, 1 is default 17 | -f, --file "filename" save statistics in file, filename is optional, 18 | default is 'netproc.log' 19 | -h, --help show this message 20 | -i, --interface iface specifies an interface, default is all 21 | (except interface with network 127.0.0.0/8) 22 | -n numeric host and service, implicit '-c', try '-nh' to no 23 | translate only host or '-np' to not translate only service 24 | -p, --protocol tcp|udp specifies a protocol, the default is tcp and udp 25 | --si show SI format, with powers of 1000, default is IEC, 26 | with powers of 1024 27 | -v, --verbose verbose mode, also show process without traffic 28 | -V, --version show version 29 | 30 | RUNNING CONTROL 31 | 32 | arrow keys scroll 33 | s change column-based sort 34 | q exit 35 | 36 | EXAMPLES 37 | This command will display the ips / ports of the udp traffic of the processes, 38 | monitoring all available interfaces, except the loopback, and log a summary 39 | in the file "log.txt": 40 | 41 | # netproc -p udp -c -f "log.txt" 42 | 43 | Useful to monitor the file generated in the above command: 44 | 45 | $ watch -t -d 'cat log.txt' 46 | $ watch -t 'cut -c -$COLUMNS log.txt' 47 | 48 | Running whitout root: 49 | 50 | $ sudo setcap "cap_net_admin,cap_net_raw+pe" /usr/local/sbin/netproc 51 | $ export PATH=$PATH:/usr/local/sbin 52 | 53 | BUGS 54 | Help improve this software, report bugs at 55 | 56 | https://github.com/berghetti/netproc/issues 57 | 58 | AUTHOR 59 | Mayco Souza Berghetti 60 | 61 | COPYRIGHT 62 | Copyright © 2020-2021 Mayco S. Berghetti. Licensed GPLv3+: GNU GPL version 3 or later . 63 | This is free software: you are free to change and redistribute it. 64 | There is NO WARRANTY, to the extent permitted by law. 65 | -------------------------------------------------------------------------------- /get_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | git describe 2>/dev/null | cut -d '-' -f 1 3 | -------------------------------------------------------------------------------- /img/print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berghetti/netproc/d6b22e19728dca1aab81442a89cf07b0574370cc/img/print.png -------------------------------------------------------------------------------- /obj/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berghetti/netproc/d6b22e19728dca1aab81442a89cf07b0574370cc/obj/.gitkeep -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Example: 4 | # $ ./release 0.1.0 5 | 6 | make_release() 7 | { 8 | sed -i "s/PROG_VERSION[ \t]\+\"\(.\+\)\"/PROG_VERSION \"$1\"/" src/config.h 9 | git add src/config.h 10 | git commit -m "set version $1" 11 | git tag -s $1 -m "version $1" 12 | } 13 | 14 | if [ -z "$1" ]; then 15 | exit 1 16 | fi 17 | 18 | make_release $1 19 | -------------------------------------------------------------------------------- /src/bpf/program.bpf: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* 22 | sudo apt install netsniff-ng, to get program bpfc 23 | usage ex: bpfc -i program.bpf -f C -p -D TCP (or UDP) 24 | 25 | pass ipv4 and tcp or udp 26 | suport to interface ethernet and 27 | interface tun (that not has header ethernet) 28 | */ 29 | 30 | #define P_TCP 0x06 31 | #define P_UDP 0x11 32 | 33 | #if UDP 34 | #define PROTO P_UDP 35 | #elif TCP 36 | #define PROTO P_TCP 37 | #endif 38 | 39 | /* test in interface tun */ 40 | l0: ldb [0] /* load offset */ 41 | l1: and #0xf0 /* bitwise and */ 42 | l2: jeq #0x40, l3, l15 /* if ipv4 true */ 43 | l3: ld [12] /* test source ip */ 44 | l4: and #0xff000000 45 | l5: jeq #0x7f000000, drop, l6 /* drop src network 127.0.0.0/8 */ 46 | l6: ld [16] /* test dest ip */ 47 | l7: and #0xff000000 48 | l8: jeq #0x7f000000, drop, l9 /* drop dst network 127.0.0.0/8 */ 49 | l9: ldb [9] /* load offset l4*/ 50 | #ifdef PROTO 51 | l10: jeq #PROTO, pass, l15 /* if protocol true */ 52 | #else 53 | l10: jeq #P_TCP, pass, l11 /* if tcp */ 54 | l11: jeq #P_UDP, pass, l15 /* if udp */ 55 | #endif 56 | 57 | /* test in interface ethernet */ 58 | l15: ldh [12] /* load half-word offset 12 */ 59 | l20: jeq #0x0800, l25, drop /* if ipv4 */ 60 | l25: ld [26] /* test source ip */ 61 | l30: and #0xff000000 62 | l35: jeq #0x7f000000, drop, l40 /* drop network 127.0.0.0/8 */ 63 | l40: ld [30] /* test dest ip */ 64 | l45: and #0xff000000 65 | l50: jeq #0x7f000000, drop, l55 /* drop network 127.0.0.0/8 */ 66 | l55: ldb [23] 67 | #ifdef PROTO 68 | l60: jeq #PROTO, pass, drop /* if protocol true */ 69 | #else 70 | l60: jeq #P_TCP, pass, l65 /* if tcp true */ 71 | l65: jeq #P_UDP, pass, drop /* if udp true */ 72 | #endif 73 | pass: ret #262144 74 | drop: ret #0 75 | -------------------------------------------------------------------------------- /src/color.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include "color.h" 23 | 24 | // colors foreground_background 25 | #define WHITE_DEFAULT 1 26 | #define WHITE_YELLOW 2 27 | #define WHITE_BLUE 3 28 | #define WHITE_MAGENTA 4 29 | #define BLACK_GREEN 5 30 | #define BLACK_CYAN 6 31 | #define BLACK_BLUE 7 32 | #define BLUE_DEFAULT 8 33 | #define CYAN_DEFAULT 9 34 | #define CYAN_BLACK 10 35 | #define BLUE_BLACK 11 36 | 37 | enum schemes 38 | { 39 | DEFAULT, 40 | ALTERNATIVE1, 41 | MONO, 42 | TOT_SCHEMES 43 | }; 44 | 45 | static const int color_schemes[TOT_SCHEMES][TOT_ELEMENTS] = { 46 | [DEFAULT] = 47 | { 48 | [RESET] = A_NORMAL | COLOR_PAIR ( WHITE_DEFAULT ), 49 | [HEADER] = COLOR_PAIR ( BLACK_GREEN ), 50 | [SELECTED_H] = COLOR_PAIR ( BLACK_CYAN ), 51 | [SELECTED_L] = COLOR_PAIR ( CYAN_BLACK ), 52 | [PATH_PROG] = COLOR_PAIR ( CYAN_DEFAULT ), 53 | [NAME_PROG] = A_BOLD | COLOR_PAIR ( CYAN_DEFAULT ), 54 | [PARAM_PROG] = A_DIM | COLOR_PAIR ( CYAN_DEFAULT ), 55 | [CONECTIONS] = A_DIM | COLOR_PAIR ( WHITE_DEFAULT ), 56 | [TREE] = COLOR_PAIR ( CYAN_DEFAULT ), 57 | [RESUME] = A_DIM | COLOR_PAIR ( WHITE_DEFAULT ), 58 | [RESUME_VALUE] = COLOR_PAIR ( CYAN_DEFAULT ), 59 | }, 60 | [ALTERNATIVE1] = 61 | { 62 | [RESET] = A_NORMAL | COLOR_PAIR ( WHITE_DEFAULT ), 63 | [HEADER] = COLOR_PAIR ( BLACK_BLUE ), 64 | [SELECTED_H] = COLOR_PAIR ( WHITE_BLUE ), 65 | [SELECTED_L] = COLOR_PAIR ( BLUE_BLACK ), 66 | [PATH_PROG] = COLOR_PAIR ( BLUE_DEFAULT ), 67 | [NAME_PROG] = A_BOLD | COLOR_PAIR ( BLUE_DEFAULT ), 68 | [PARAM_PROG] = A_DIM | COLOR_PAIR ( BLUE_DEFAULT ), 69 | [CONECTIONS] = A_DIM | COLOR_PAIR ( WHITE_DEFAULT ), 70 | [TREE] = A_DIM | COLOR_PAIR ( BLUE_DEFAULT ), 71 | [RESUME] = A_DIM | COLOR_PAIR ( WHITE_DEFAULT ), 72 | [RESUME_VALUE] = COLOR_PAIR ( BLUE_DEFAULT ), 73 | }, 74 | [MONO] = { 75 | [RESET] = A_NORMAL, 76 | [HEADER] = A_REVERSE, 77 | [SELECTED_H] = A_DIM | A_REVERSE, 78 | [SELECTED_L] = A_DIM | A_REVERSE, 79 | [PATH_PROG] = A_DIM, 80 | [NAME_PROG] = A_BOLD, 81 | [PARAM_PROG] = A_DIM, 82 | [CONECTIONS] = A_DIM, 83 | [TREE] = A_DIM, 84 | [RESUME] = A_DIM, 85 | [RESUME_VALUE] = A_NORMAL, 86 | }}; 87 | 88 | static void 89 | pairs_init ( void ) 90 | { 91 | init_pair ( CYAN_DEFAULT, COLOR_CYAN, -1 ); // color tree, name program 92 | init_pair ( BLACK_GREEN, COLOR_BLACK, COLOR_GREEN ); // color header 93 | init_pair ( BLACK_CYAN, COLOR_BLACK, COLOR_CYAN ); 94 | init_pair ( WHITE_DEFAULT, COLOR_WHITE, -1 ); 95 | init_pair ( WHITE_BLUE, COLOR_WHITE, COLOR_BLUE ); 96 | init_pair ( WHITE_MAGENTA, COLOR_WHITE, COLOR_MAGENTA ); 97 | init_pair ( BLUE_DEFAULT, COLOR_BLUE, -1 ); 98 | init_pair ( WHITE_YELLOW, COLOR_WHITE, COLOR_YELLOW ); 99 | init_pair ( BLACK_BLUE, COLOR_BLACK, COLOR_BLUE ); 100 | init_pair ( BLUE_BLACK, COLOR_BLUE, COLOR_BLACK ); 101 | init_pair ( CYAN_BLACK, COLOR_CYAN, COLOR_BLACK ); 102 | } 103 | 104 | int * 105 | get_color_scheme ( const int color_scheme ) 106 | { 107 | if ( !has_colors () ) 108 | return ( int * ) color_schemes[MONO]; 109 | 110 | start_color (); 111 | 112 | if ( use_default_colors () == ERR ) 113 | assume_default_colors ( COLOR_WHITE, COLOR_BLACK ); 114 | 115 | pairs_init (); 116 | 117 | return ( int * ) color_schemes[color_scheme]; 118 | } 119 | -------------------------------------------------------------------------------- /src/color.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef COLOR_H 22 | #define COLOR_H 23 | 24 | #include "config.h" // struct config_op 25 | 26 | enum elements_in_schemes 27 | { 28 | RESET, 29 | HEADER, 30 | SELECTED_H, 31 | SELECTED_L, 32 | PATH_PROG, 33 | NAME_PROG, 34 | PARAM_PROG, 35 | CONECTIONS, 36 | TREE, 37 | RESUME, 38 | RESUME_VALUE, 39 | TOT_ELEMENTS 40 | }; 41 | 42 | int * 43 | get_color_scheme ( const int color_scheme ); 44 | 45 | #endif // COLOR_H 46 | -------------------------------------------------------------------------------- /src/config.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include // exit 24 | #include // strncmp 25 | #include // EXIT_* 26 | 27 | #include "config.h" 28 | #include "connection.h" 29 | #include "usage.h" 30 | #include "macro_util.h" 31 | 32 | // default options 33 | static struct config_op co = { .iface = NULL, // all interfaces 34 | .path_log = PROG_NAME_LOG, 35 | .log = false, 36 | .proto = TCP | UDP, 37 | .color_scheme = 0, 38 | .view_si = false, 39 | .view_bytes = false, 40 | .view_conections = false, 41 | .translate_host = true, 42 | .translate_service = true, 43 | .verbose = false, 44 | .running = 0 }; 45 | 46 | static void 47 | fatal_config ( const char *msg ) 48 | { 49 | fprintf ( stderr, 50 | "%s\n" 51 | "See " PROG_NAME " --help\n", 52 | msg ); 53 | exit ( EXIT_FAILURE ); 54 | } 55 | 56 | static void 57 | view_bytes ( UNUSED char *arg ) 58 | { 59 | co.view_bytes = true; 60 | } 61 | static void 62 | view_conections ( UNUSED char *arg ) 63 | { 64 | co.view_conections = true; 65 | } 66 | 67 | static void 68 | color_scheme ( char *arg ) 69 | { 70 | int value; 71 | if ( !arg || !( value = atoi ( arg ) ) ) 72 | fatal_config ( "Argument '--color' requires a valid color scheme number" ); 73 | 74 | // 0, 1 or 2 75 | value &= 0x3; 76 | co.color_scheme = value - ( value != 0 ); 77 | } 78 | 79 | static void 80 | log_file ( char *arg ) 81 | { 82 | co.log = true; 83 | 84 | if ( arg ) 85 | co.path_log = arg; 86 | } 87 | 88 | static void 89 | show_help ( UNUSED char *arg ) 90 | { 91 | usage (); 92 | exit ( EXIT_SUCCESS ); 93 | } 94 | 95 | static void 96 | iface ( char *arg ) 97 | { 98 | if ( !arg ) 99 | fatal_config ( "Argument '-i' requere interface name" ); 100 | 101 | co.iface = arg; 102 | } 103 | 104 | static void 105 | show_numeric_host ( UNUSED char *arg ) 106 | { 107 | co.view_conections = true; 108 | co.translate_host = false; 109 | } 110 | static void 111 | show_numeric_port ( UNUSED char *arg ) 112 | { 113 | co.view_conections = true; 114 | co.translate_service = false; 115 | } 116 | 117 | static void 118 | show_numeric ( UNUSED char *arg ) 119 | { 120 | show_numeric_host ( NULL ); 121 | show_numeric_port ( NULL ); 122 | } 123 | 124 | static void 125 | set_proto ( char *arg ) 126 | { 127 | if ( !arg ) 128 | fatal_config ( "Argument '-p' requere udp or tcp argument" ); 129 | else if ( !strcasecmp ( arg, "tcp" ) ) 130 | co.proto &= TCP; 131 | else if ( !strcasecmp ( arg, "udp" ) ) 132 | co.proto &= UDP; 133 | else 134 | fatal_config ( "Invalid protocol in argument '-p'" ); 135 | } 136 | 137 | static void 138 | view_si ( UNUSED char *arg ) 139 | { 140 | co.view_si = true; 141 | } 142 | 143 | static void 144 | verbose ( UNUSED char *arg ) 145 | { 146 | co.verbose = true; 147 | } 148 | 149 | static void 150 | version ( UNUSED char *arg ) 151 | { 152 | show_version (); 153 | exit ( EXIT_SUCCESS ); 154 | } 155 | 156 | struct cmd 157 | { 158 | char *cur_opt; 159 | char *long_opt; 160 | void ( *func ) ( char * ); 161 | int req_arg; 162 | }; 163 | 164 | // cmd.req_arg values 165 | #define NO_ARG 0 166 | #define REQ_ARG 1 167 | #define OPT_ARG 2 168 | 169 | static inline int 170 | check_cmd ( char *arg, const struct cmd *cmd ) 171 | { 172 | return !strcmp ( arg, cmd->cur_opt ) || !strcmp ( arg, cmd->long_opt ); 173 | } 174 | 175 | struct config_op * 176 | parse_options ( int argc, char **argv ) 177 | { 178 | static const struct cmd cmd[] = { { "-B", "--bytes", view_bytes, NO_ARG }, 179 | { "-c", "", view_conections, NO_ARG }, 180 | { "", "--color", color_scheme, REQ_ARG }, 181 | { "-f", "--file", log_file, OPT_ARG }, 182 | { "-h", "--help", show_help, NO_ARG }, 183 | { "-i", "--interface", iface, REQ_ARG }, 184 | { "-n", "", show_numeric, NO_ARG }, 185 | { "-nh", "", show_numeric_host, NO_ARG }, 186 | { "-np", "", show_numeric_port, NO_ARG }, 187 | { "-p", "--protocol", set_proto, REQ_ARG }, 188 | { "", "--si", view_si, NO_ARG }, 189 | { "-v", "--verbose", verbose, NO_ARG }, 190 | { "-V", "--version", version, NO_ARG } }; 191 | 192 | while ( --argc ) 193 | { 194 | int check = 0; 195 | argv++; 196 | 197 | for ( unsigned int i = 0; i < ARRAY_SIZE ( cmd ); i++ ) 198 | { 199 | check = check_cmd ( *argv, &cmd[i] ); 200 | if ( check ) 201 | { 202 | char *arg = NULL; 203 | 204 | switch ( cmd[i].req_arg ) 205 | { 206 | case REQ_ARG: 207 | argv++; 208 | argc--; 209 | arg = *argv; 210 | break; 211 | case OPT_ARG: 212 | argv++; 213 | if ( *argv == NULL || **argv == '-' ) 214 | { 215 | argv--; 216 | break; 217 | } 218 | 219 | argc--; 220 | arg = *argv; 221 | } 222 | 223 | cmd[i].func ( arg ); 224 | break; 225 | } 226 | } 227 | 228 | if ( !check ) 229 | { 230 | fprintf ( stderr, 231 | "Invalid Argument '%s'\n" 232 | "See " PROG_NAME " --help\n", 233 | *argv ); 234 | exit ( EXIT_FAILURE ); 235 | } 236 | } 237 | 238 | return &co; 239 | } 240 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef CONFIG_H 22 | #define CONFIG_H 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #define PROG_NAME "netproc" 29 | #define PROG_NAME_LOG PROG_NAME ".log" 30 | 31 | #define PROG_VERSION "0.6.7" 32 | 33 | // values struct config_op.proto 34 | #define TCP ( 1 << 0 ) 35 | #define UDP ( 1 << 1 ) 36 | 37 | struct config_op 38 | { 39 | char *iface; // bind interface 40 | char *path_log; // path to log in file 41 | uint64_t running; // time the program is running 42 | int proto; // tcp or udp 43 | int color_scheme; 44 | bool log; // log in file 45 | bool view_si; // SI or IEC prefix 46 | bool view_bytes; // view in bytes or bits 47 | bool view_conections; // show conections each process 48 | bool translate_host; // translate ip to name using DNS 49 | bool translate_service; // translate port to service 50 | bool verbose; // show process without traffic alse 51 | }; 52 | 53 | struct config_op * 54 | parse_options ( int argc, char **argv ); 55 | 56 | #endif // CONFIG_H 57 | -------------------------------------------------------------------------------- /src/connection.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | // references 22 | // https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt 23 | 24 | #include // variable errno 25 | #include 26 | #include // FILE * 27 | #include // strlen, strerror 28 | #include // TCP_ESTABLISHED, TCP_TIME_WAIT... 29 | 30 | #include "connection.h" 31 | #include "hashtable.h" 32 | #include "jhash.h" 33 | #include "config.h" // define TCP | UDP 34 | #include "m_error.h" 35 | #include "macro_util.h" 36 | 37 | static hashtable_t *ht_connections = NULL; 38 | 39 | static hash_t 40 | hash ( const void *key, size_t size ) 41 | { 42 | return jhash8 ( key, size, 0 ); 43 | } 44 | 45 | static bool 46 | ht_cb_compare_inode ( const void *key1, const void *key2 ) 47 | { 48 | if ( key1 == key2 ) 49 | return true; 50 | 51 | return ( *( unsigned long * ) key1 == *( unsigned long * ) key2 ); 52 | } 53 | 54 | static bool 55 | ht_cb_compare_tuple ( const void *key1, const void *key2 ) 56 | { 57 | if ( key1 == key2 ) 58 | return true; 59 | 60 | return ( 0 == memcmp ( key1, key2, sizeof ( struct tuple ) ) ); 61 | } 62 | 63 | #define MARK_ACTIVE_CON( conn ) ( ( conn )->refs_active = 3 ) 64 | 65 | static connection_t * 66 | create_new_conn ( unsigned long inode, 67 | char *local_addr, 68 | char *remote_addr, 69 | uint16_t local_port, 70 | uint16_t rem_port, 71 | uint8_t state, 72 | int protocol ) 73 | { 74 | /* using calloc to ensure that struct tuple is clean 75 | necessary to struct net_stat */ 76 | connection_t *conn = calloc ( 1, sizeof *conn ); 77 | if ( !conn ) 78 | { 79 | ERROR_DEBUG ( "\"%s\"", strerror ( errno ) ); 80 | return NULL; 81 | } 82 | 83 | int rs = sscanf ( local_addr, "%x", &conn->tuple.l3.local.ip ); 84 | 85 | if ( 1 != rs ) 86 | goto EXIT_ERROR; 87 | 88 | rs = sscanf ( remote_addr, "%x", &conn->tuple.l3.remote.ip ); 89 | 90 | if ( 1 != rs ) 91 | goto EXIT_ERROR; 92 | 93 | conn->tuple.l4.local_port = local_port; 94 | conn->tuple.l4.remote_port = rem_port; 95 | conn->tuple.l4.protocol = protocol; 96 | conn->state = state; 97 | conn->inode = inode; 98 | 99 | /* each conn has two entries on hashtable, 100 | this is used to remove inactives conns and free only one time a conn */ 101 | MARK_ACTIVE_CON ( conn ); 102 | 103 | return conn; 104 | 105 | EXIT_ERROR: 106 | ERROR_DEBUG ( "\"%s\"", strerror ( errno ) ); 107 | free ( conn ); 108 | return NULL; 109 | } 110 | 111 | static void 112 | connection_insert ( connection_t *conn ) 113 | { 114 | // make one entries in hashtable to same connection 115 | hashtable_min_set ( 116 | ht_connections, 117 | conn, 118 | &conn->inode, 119 | hash ( &conn->inode, SIZEOF_MEMBER ( connection_t, inode ) ) ); 120 | 121 | hashtable_min_set ( 122 | ht_connections, 123 | conn, 124 | &conn->tuple, 125 | hash ( &conn->tuple, SIZEOF_MEMBER ( connection_t, tuple ) ) ); 126 | } 127 | 128 | static int 129 | connection_update_ ( const char *path_file, const int protocol ) 130 | { 131 | FILE *arq = fopen ( path_file, "r" ); 132 | if ( !arq ) 133 | { 134 | ERROR_DEBUG ( "\"%s\"", strerror ( errno ) ); 135 | return 0; 136 | } 137 | 138 | int ret = 1; 139 | char *line = NULL; 140 | size_t len = 0; 141 | 142 | // ignore header in first line 143 | if ( ( getline ( &line, &len, arq ) ) == -1 ) 144 | { 145 | ERROR_DEBUG ( "\"%s\"", strerror ( errno ) ); 146 | ret = 0; 147 | goto EXIT; 148 | } 149 | 150 | while ( ( getline ( &line, &len, arq ) ) != -1 ) 151 | { 152 | /* clang-format off 153 | sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode 154 | 0: 3500007F:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000 101 0 20911 1 0000000000000000 100 0 0 10 0 155 | 1: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 44385 1 0000000000000000 100 0 0 10 0 156 | 2: 0100007F:1733 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 27996 1 0000000000000000 100 0 0 10 0 157 | clang-format on */ 158 | 159 | char local_addr[10], rem_addr[10]; // enough for ipv4 160 | unsigned long inode; 161 | uint16_t local_port, rem_port; 162 | uint8_t state; 163 | int rs = sscanf ( line, 164 | "%*d: %9[0-9A-Fa-f]:%hX %9[0-9A-Fa-f]:%hX %hhX" 165 | " %*X:%*X %*X:%*X %*X %*d %*d %lu %*512s\n", 166 | local_addr, 167 | &local_port, 168 | rem_addr, 169 | &rem_port, 170 | &state, 171 | &inode ); 172 | 173 | if ( rs != 6 ) 174 | { 175 | ERROR_DEBUG ( "Error read file conections\"%s\"", 176 | strerror ( errno ) ); 177 | ret = 0; 178 | goto EXIT; 179 | } 180 | 181 | // ignore this conections 182 | if ( state == TCP_TIME_WAIT || state == TCP_LISTEN ) 183 | continue; 184 | 185 | // TODO: need check to tuple here? linux recycling inode? 186 | connection_t *conn = connection_get_by_inode ( inode ); 187 | 188 | if ( conn ) 189 | { 190 | MARK_ACTIVE_CON ( conn ); 191 | continue; 192 | } 193 | 194 | conn = create_new_conn ( inode, 195 | local_addr, 196 | rem_addr, 197 | local_port, 198 | rem_port, 199 | state, 200 | protocol ); 201 | if ( !conn ) 202 | { 203 | ret = 0; 204 | goto EXIT; 205 | } 206 | 207 | connection_insert ( conn ); 208 | } 209 | 210 | EXIT: 211 | free ( line ); 212 | fclose ( arq ); 213 | 214 | return ret; 215 | } 216 | 217 | static int 218 | remove_inactives_conns ( UNUSED hashtable_t *ht, 219 | void *value, 220 | UNUSED void *user_data ) 221 | { 222 | connection_t *conn = value; 223 | 224 | switch ( conn->refs_active-- ) 225 | { 226 | case 1: 227 | return 1; 228 | 229 | case 0: 230 | free ( conn ); 231 | return 1; 232 | 233 | default: 234 | return 0; 235 | } 236 | } 237 | 238 | bool 239 | connection_init ( void ) 240 | { 241 | ht_connections = hashtable_min_new (); 242 | 243 | return !!ht_connections; 244 | } 245 | 246 | #define PATH_TCP "/proc/net/tcp" 247 | #define PATH_UDP "/proc/net/udp" 248 | 249 | bool 250 | connection_update ( const int proto ) 251 | { 252 | hashtable_foreach_remove ( ht_connections, remove_inactives_conns, NULL ); 253 | 254 | if ( proto & TCP ) 255 | { 256 | if ( !connection_update_ ( PATH_TCP, IPPROTO_TCP ) ) 257 | return false; 258 | } 259 | 260 | if ( proto & UDP ) 261 | { 262 | if ( !connection_update_ ( PATH_UDP, IPPROTO_UDP ) ) 263 | return false; 264 | } 265 | 266 | return true; 267 | } 268 | 269 | connection_t * 270 | connection_get_by_inode ( const unsigned long inode ) 271 | { 272 | return hashtable_min_get ( ht_connections, 273 | &inode, 274 | hash ( &inode, sizeof ( inode ) ), 275 | ht_cb_compare_inode ); 276 | } 277 | 278 | connection_t * 279 | connection_get_by_tuple ( struct tuple *tuple ) 280 | { 281 | return hashtable_min_get ( 282 | ht_connections, 283 | tuple, 284 | hash ( tuple, SIZEOF_MEMBER ( connection_t, tuple ) ), 285 | ht_cb_compare_tuple ); 286 | } 287 | 288 | static void 289 | conn_free ( void *data ) 290 | { 291 | connection_t *conn = data; 292 | 293 | /* first entry go be 0, not free, remove second entry */ 294 | if ( conn->refs_exit++ == 1 ) 295 | free ( conn ); 296 | } 297 | 298 | void 299 | connection_free ( void ) 300 | { 301 | if ( ht_connections ) 302 | hashtable_min_detroy ( ht_connections, conn_free ); 303 | } 304 | -------------------------------------------------------------------------------- /src/connection.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef CONECTION_H 22 | #define CONECTION_H 23 | 24 | #include 25 | #include 26 | 27 | #include "rate.h" // struct net_stat 28 | #include "sockaddr.h" 29 | 30 | // forward declaration 31 | typedef struct process process_t; 32 | 33 | /* stores the information exported by the kernel in /proc/net/tcp | udp. 34 | each conn has two entries in hashtable, one with key inode and other with key 35 | tuple */ 36 | typedef struct conection 37 | { 38 | struct net_stat net_stat; // assign in statistics.c 39 | struct tuple tuple; // layer 3 and 4 info 40 | process_t *proc; // process the connection belongs to 41 | unsigned long inode; // kernel linux usage this type to inode 42 | int if_index; // assign in statistics.c 43 | uint8_t state; // status tcp connection 44 | 45 | // internal state 46 | uint8_t refs_active; // if 1 connection is removed from ht, if 0 connection 47 | // is removed from ht and free 48 | uint8_t refs_exit; // usage to cleanup hashtable 49 | } connection_t; 50 | 51 | bool 52 | connection_init ( void ); 53 | 54 | bool 55 | connection_update ( const int proto ); 56 | 57 | connection_t * 58 | connection_get_by_inode ( const unsigned long inode ); 59 | 60 | connection_t * 61 | connection_get_by_tuple ( struct tuple *tuple ); 62 | 63 | void 64 | connection_free ( void ); 65 | 66 | #endif // CONECTION_H 67 | -------------------------------------------------------------------------------- /src/directory.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include // isdigit 24 | #include // *dir 25 | #include // type boolean 26 | #include // type uint* 27 | #include // malloc 28 | #include // memset 29 | #include // *dir 30 | 31 | #include "m_error.h" 32 | 33 | #define ENTRY_SIZE_BUF 128 34 | 35 | // -1 failure 36 | int 37 | get_numeric_directory ( uint32_t **buffer, const char *path_dir ) 38 | { 39 | DIR *dir; 40 | if ( ( dir = opendir ( path_dir ) ) == NULL ) 41 | { 42 | ERROR_DEBUG ( "%s - %s", path_dir, strerror ( errno ) ); 43 | return -1; 44 | } 45 | 46 | errno = 0; 47 | int count = 0; 48 | int len_buffer = 0; 49 | struct dirent *directory; 50 | while ( ( directory = readdir ( dir ) ) ) 51 | { 52 | if ( count == len_buffer ) 53 | { 54 | len_buffer += ENTRY_SIZE_BUF; 55 | void *temp; 56 | temp = realloc ( *buffer, len_buffer * sizeof ( **buffer ) ); 57 | 58 | if ( !temp ) 59 | { 60 | errno = 0; 61 | goto END; 62 | } 63 | 64 | *buffer = temp; 65 | } 66 | 67 | char crap; 68 | int rs = sscanf ( directory->d_name, "%u%c", &( *buffer )[count], &crap ); 69 | 70 | if ( rs != 1 ) 71 | continue; 72 | 73 | count++; 74 | } 75 | 76 | if ( errno ) 77 | { 78 | ERROR_DEBUG ( "%s", strerror ( errno ) ); 79 | count = -1; 80 | } 81 | 82 | END: 83 | closedir ( dir ); 84 | 85 | return count; 86 | } 87 | -------------------------------------------------------------------------------- /src/directory.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef DIRECTORY_H 22 | #define DIRECTORY_H 23 | 24 | #include 25 | #include 26 | 27 | // return -1 on failure or number of found directories 28 | int 29 | get_numeric_directory ( uint32_t **buffer, const char *path_dir ); 30 | 31 | #endif // DIRECTORY_H 32 | -------------------------------------------------------------------------------- /src/filter.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include // struct sock_filter, sock_fprog 23 | #include // setsockopt 24 | 25 | #include "connection.h" 26 | #include "m_error.h" 27 | #include "macro_util.h" 28 | 29 | static bool 30 | filter_get ( struct sock_fprog *fprog, const int flags_proto ) 31 | { 32 | // pass only tcp or udp, block net address 127.* 33 | // suport interface ethernet and tun 34 | // bpfc -i bpf/program.bpf -f C -p 35 | static const struct sock_filter ip_tcp_udp[] = { 36 | { 0x30, 0, 0, 0x00000000 }, { 0x54, 0, 0, 0x000000f0 }, 37 | { 0x15, 0, 9, 0x00000040 }, { 0x20, 0, 0, 0x0000000c }, 38 | { 0x54, 0, 0, 0xff000000 }, { 0x15, 18, 0, 0x7f000000 }, 39 | { 0x20, 0, 0, 0x00000010 }, { 0x54, 0, 0, 0xff000000 }, 40 | { 0x15, 15, 0, 0x7f000000 }, { 0x30, 0, 0, 0x00000009 }, 41 | { 0x15, 12, 0, 0x00000006 }, { 0x15, 11, 0, 0x00000011 }, 42 | { 0x28, 0, 0, 0x0000000c }, { 0x15, 0, 10, 0x00000800 }, 43 | { 0x20, 0, 0, 0x0000001a }, { 0x54, 0, 0, 0xff000000 }, 44 | { 0x15, 7, 0, 0x7f000000 }, { 0x20, 0, 0, 0x0000001e }, 45 | { 0x54, 0, 0, 0xff000000 }, { 0x15, 4, 0, 0x7f000000 }, 46 | { 0x30, 0, 0, 0x00000017 }, { 0x15, 1, 0, 0x00000006 }, 47 | { 0x15, 0, 1, 0x00000011 }, { 0x6, 0, 0, 0x00040000 }, 48 | { 0x6, 0, 0, 0x00000000 }, 49 | }; 50 | 51 | // pass only tcp, block net address 127.* 52 | // suport interface ethernet and tun 53 | // bpfc -i bpf/program.bpf -f C -p -D TCP 54 | static const struct sock_filter ip_tcp[] = { 55 | { 0x30, 0, 0, 0x00000000 }, { 0x54, 0, 0, 0x000000f0 }, 56 | { 0x15, 0, 8, 0x00000040 }, { 0x20, 0, 0, 0x0000000c }, 57 | { 0x54, 0, 0, 0xff000000 }, { 0x15, 16, 0, 0x7f000000 }, 58 | { 0x20, 0, 0, 0x00000010 }, { 0x54, 0, 0, 0xff000000 }, 59 | { 0x15, 13, 0, 0x7f000000 }, { 0x30, 0, 0, 0x00000009 }, 60 | { 0x15, 10, 0, 0x00000006 }, { 0x28, 0, 0, 0x0000000c }, 61 | { 0x15, 0, 9, 0x00000800 }, { 0x20, 0, 0, 0x0000001a }, 62 | { 0x54, 0, 0, 0xff000000 }, { 0x15, 6, 0, 0x7f000000 }, 63 | { 0x20, 0, 0, 0x0000001e }, { 0x54, 0, 0, 0xff000000 }, 64 | { 0x15, 3, 0, 0x7f000000 }, { 0x30, 0, 0, 0x00000017 }, 65 | { 0x15, 0, 1, 0x00000006 }, { 0x6, 0, 0, 0x00040000 }, 66 | { 0x6, 0, 0, 0x00000000 }, 67 | }; 68 | 69 | // pass only udp, block net address 127.* 70 | // suport interface ethernet and tun 71 | // bpfc -i bpf/program.bpf -f C -p -D UDP 72 | static const struct sock_filter ip_udp[] = { 73 | { 0x30, 0, 0, 0x00000000 }, { 0x54, 0, 0, 0x000000f0 }, 74 | { 0x15, 0, 8, 0x00000040 }, { 0x20, 0, 0, 0x0000000c }, 75 | { 0x54, 0, 0, 0xff000000 }, { 0x15, 16, 0, 0x7f000000 }, 76 | { 0x20, 0, 0, 0x00000010 }, { 0x54, 0, 0, 0xff000000 }, 77 | { 0x15, 13, 0, 0x7f000000 }, { 0x30, 0, 0, 0x00000009 }, 78 | { 0x15, 10, 0, 0x00000011 }, { 0x28, 0, 0, 0x0000000c }, 79 | { 0x15, 0, 9, 0x00000800 }, { 0x20, 0, 0, 0x0000001a }, 80 | { 0x54, 0, 0, 0xff000000 }, { 0x15, 6, 0, 0x7f000000 }, 81 | { 0x20, 0, 0, 0x0000001e }, { 0x54, 0, 0, 0xff000000 }, 82 | { 0x15, 3, 0, 0x7f000000 }, { 0x30, 0, 0, 0x00000017 }, 83 | { 0x15, 0, 1, 0x00000011 }, { 0x6, 0, 0, 0x00040000 }, 84 | { 0x6, 0, 0, 0x00000000 }, 85 | }; 86 | 87 | switch ( flags_proto ) 88 | { 89 | case ( TCP | UDP ): 90 | fprog->len = ARRAY_SIZE ( ip_tcp_udp ); 91 | fprog->filter = ( struct sock_filter * ) ip_tcp_udp; 92 | break; 93 | case TCP: 94 | fprog->len = ARRAY_SIZE ( ip_tcp ); 95 | fprog->filter = ( struct sock_filter * ) ip_tcp; 96 | break; 97 | case UDP: 98 | fprog->len = ARRAY_SIZE ( ip_udp ); 99 | fprog->filter = ( struct sock_filter * ) ip_udp; 100 | break; 101 | default: 102 | ERROR_DEBUG ( "%s", "Protocol filter bpf invalid" ); 103 | return false; 104 | } 105 | 106 | return true; 107 | } 108 | 109 | bool 110 | filter_set ( int sock, const int flags_proto ) 111 | { 112 | struct sock_fprog fprog; 113 | 114 | if ( !filter_get ( &fprog, flags_proto ) ) 115 | return false; 116 | 117 | if ( setsockopt ( sock, 118 | SOL_SOCKET, 119 | SO_ATTACH_FILTER, 120 | &fprog, 121 | sizeof ( fprog ) ) == -1 ) 122 | { 123 | ERROR_DEBUG ( "\"%s\"", strerror ( errno ) ); 124 | return false; 125 | } 126 | 127 | return true; 128 | } 129 | -------------------------------------------------------------------------------- /src/filter.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef FILTER_H 22 | #define FILTER_H 23 | 24 | #include 25 | 26 | bool 27 | filter_set ( int sock, const int flags_proto ); 28 | 29 | #endif // FILTER_H 30 | -------------------------------------------------------------------------------- /src/full_read.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // errno 22 | #include // realloc 23 | #include // read 24 | 25 | #define ENTRY_SIZE_BUFF 64 26 | 27 | ssize_t 28 | full_read ( const int fd, char **buffer ) 29 | { 30 | size_t count = 0; 31 | size_t buff_size = 0; 32 | ssize_t total_read = 0; 33 | char *p_buf; 34 | 35 | *buffer = NULL; 36 | while ( 1 ) 37 | { 38 | if ( !count ) 39 | { 40 | count = ENTRY_SIZE_BUFF; 41 | buff_size += ENTRY_SIZE_BUFF; 42 | char *t = realloc ( *buffer, buff_size ); 43 | if ( !t ) 44 | goto ERROR_EXIT; 45 | 46 | *buffer = t; 47 | p_buf = t + total_read; 48 | } 49 | 50 | ssize_t bytes_read = read ( fd, p_buf, count ); 51 | 52 | if ( bytes_read == -1 ) 53 | { 54 | if ( errno != EINTR ) 55 | goto ERROR_EXIT; 56 | 57 | continue; 58 | } 59 | else if ( bytes_read ) 60 | { 61 | p_buf += bytes_read; 62 | count -= bytes_read; 63 | total_read += bytes_read; 64 | } 65 | else 66 | break; // EOF 67 | } 68 | 69 | return total_read; 70 | 71 | ERROR_EXIT: 72 | 73 | free ( *buffer ); 74 | return -1; 75 | } 76 | -------------------------------------------------------------------------------- /src/full_read.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef FULL_READ_H 22 | #define FULL_READ_H 23 | 24 | /* read all data from file descriptor fd and alloc memory necessary 25 | return total bytes read or -1 on failure, 26 | if failure is not necessary free the buffer */ 27 | ssize_t 28 | full_read ( const int fd, char **buffer ); 29 | 30 | #endif // FULL_READ_H 31 | -------------------------------------------------------------------------------- /src/hashtable.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef HASHTABLE_H 22 | #define HASHTABLE_H 23 | 24 | #include 25 | #include // size_t 26 | 27 | typedef size_t hash_t; 28 | typedef struct hashtable hashtable_t; 29 | 30 | typedef void ( *func_clear ) ( void * ); 31 | typedef bool ( *func_compare ) ( const void *key1, const void *key2 ); 32 | typedef hash_t ( *func_hash ) ( const void *data ); 33 | typedef int ( *hashtable_foreach_func ) ( hashtable_t *ht, 34 | void *value, 35 | void *user_data ); 36 | 37 | /* all function that return a pointer, return NULL on error, 38 | some functions has two version as 'hashtable_set' and 'hashtable_min_set' 39 | the version with 'min' in name is used internament and can be used by user to 40 | a more generic use */ 41 | 42 | hashtable_t * 43 | hashtable_min_new ( void ); 44 | 45 | hashtable_t * 46 | hashtable_new ( func_hash fhash, func_compare fcompare, func_clear fclear ); 47 | 48 | /* return pointer value for convenience on sucess */ 49 | void * 50 | hashtable_min_set ( hashtable_t *ht, 51 | void *value, 52 | const void *key, 53 | const hash_t hash ); 54 | 55 | void * 56 | hashtable_set ( hashtable_t *ht, const void *key, void *value ); 57 | 58 | void * 59 | hashtable_min_get ( hashtable_t *ht, 60 | const void *key, 61 | hash_t hash, 62 | func_compare cmp ); 63 | 64 | void * 65 | hashtable_get ( hashtable_t *ht, const void *key ); 66 | 67 | size_t 68 | hashtable_get_nentries ( hashtable_t *ht ); 69 | 70 | size_t 71 | hashtable_get_size ( hashtable_t *ht ); 72 | 73 | /* to each entries in hashtable, the function 'func' is called 74 | and passes as argument the entrie and 'user_data', 75 | if 'func' return different of zero hashtable_foreach stop 76 | and return the value returned from 'func' */ 77 | int 78 | hashtable_foreach ( hashtable_t *ht, 79 | hashtable_foreach_func func, 80 | void *user_data ); 81 | 82 | /* to each entries in hashtable, the function 'to_remove' is called 83 | and passes as argument the entrie and 'user_data', 84 | if 'to_remove' return true the entry be removed from ht */ 85 | void 86 | hashtable_foreach_remove ( hashtable_t *ht, 87 | hashtable_foreach_func to_remove, 88 | void *user_data ); 89 | 90 | /* remove entry from hashtable and return a pointer to entry, 91 | the entry needs to be handled by the user's skin yet (e.g free if 92 | necessary ) 93 | */ 94 | void * 95 | hashtable_min_remove ( hashtable_t *ht, 96 | const void *key, 97 | hash_t hash, 98 | func_compare cmp ); 99 | 100 | void * 101 | hashtable_remove ( hashtable_t *ht, const void *key ); 102 | 103 | void 104 | hashtable_min_detroy ( hashtable_t *ht, func_clear fclear ); 105 | 106 | void 107 | hashtable_destroy ( hashtable_t *ht ); 108 | 109 | #endif // HASHTABLE_H 110 | -------------------------------------------------------------------------------- /src/human_readable.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // snprintf() 22 | #include 23 | #include 24 | 25 | #include "human_readable.h" 26 | 27 | #define BASE_IEC 1024 // default 28 | #define BASE_SI 1000 29 | 30 | enum sufix_types 31 | { 32 | IEC_BYTE = 0, 33 | IEC_BIT, 34 | SI_BYTE, 35 | SI_BIT, 36 | IEC_BYTE_TOT, 37 | IEC_BIT_TOT, 38 | SI_BYTE_TOT, 39 | SI_BIT_TOT, 40 | TOT_SUFIX_SCHEME 41 | }; 42 | 43 | #define TOT_ELEMENTS_SUFIX 6 44 | 45 | static const char *const sufix_schemes[TOT_SUFIX_SCHEME][TOT_ELEMENTS_SUFIX] = { 46 | [IEC_BYTE] = { "B/s", "KiB/s", "MiB/s", "GiB/s", "TiB/s", "PiB/s" }, 47 | [IEC_BIT] = { "b/s", "Kib/s", "Mib/s", "Gib/s", "Tib/s", "Pib/s" }, 48 | [SI_BYTE] = { "B/s", "KB/s", "MB/s", "GB/s", "TB/s", "PB/s" }, 49 | [SI_BIT] = { "b/s", "Kb/s", "Mb/s", "Gb/s", "Tb/s", "Pb/s" }, 50 | [IEC_BYTE_TOT] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" }, 51 | [IEC_BIT_TOT] = { "b", "Kib", "Mib", "Gib", "Tib", "Pib" }, 52 | [SI_BYTE_TOT] = { "B", "KB", "MB", "GB", "TB", "PB" }, 53 | [SI_BIT_TOT] = { "b", "Kb", "Mb", "Gb", "Tb", "Pb" } 54 | }; 55 | 56 | static unsigned int base; 57 | static const char *const *sufix_rate; 58 | static const char *const *sufix_total; 59 | 60 | void 61 | define_sufix ( const bool view_si, const bool view_bytes ) 62 | { 63 | if ( view_si ) 64 | { 65 | base = BASE_SI; 66 | 67 | if ( view_bytes ) 68 | { 69 | sufix_rate = sufix_schemes[SI_BYTE]; 70 | sufix_total = sufix_schemes[SI_BYTE_TOT]; 71 | } 72 | else // default 73 | { 74 | sufix_rate = sufix_schemes[SI_BIT]; 75 | sufix_total = sufix_schemes[SI_BIT_TOT]; 76 | } 77 | } 78 | else // default 79 | { 80 | base = BASE_IEC; 81 | 82 | if ( view_bytes ) 83 | { 84 | sufix_rate = sufix_schemes[IEC_BYTE]; 85 | sufix_total = sufix_schemes[IEC_BYTE_TOT]; 86 | } 87 | else // default 88 | { 89 | sufix_rate = sufix_schemes[IEC_BIT]; 90 | sufix_total = sufix_schemes[IEC_BIT_TOT]; 91 | } 92 | } 93 | } 94 | 95 | // based in source code of program wget 96 | // https://github.com/mirror/wget/blob/master/src/utils.c#L1675 97 | 98 | bool 99 | human_readable ( char *buffer, size_t len_buff, uint64_t bytes, int mode ) 100 | { 101 | const char *const *sufix = ( mode == RATE ) ? sufix_rate : sufix_total; 102 | 103 | ssize_t sn; 104 | 105 | if ( !bytes ) 106 | { 107 | sn = snprintf ( buffer, len_buff, "%c", '0' ); 108 | return ( sn == 1 ); 109 | } 110 | 111 | // quantidade de bytes ou bits menor que 1024 ou 1000 112 | if ( bytes < base ) 113 | { 114 | sn = snprintf ( buffer, len_buff, "%ld %s", bytes, sufix[0] ); 115 | return ( sn > 0 && ( size_t ) sn < len_buff ); 116 | } 117 | 118 | /* a cada loop os bytes/bits recebidos são divididos por sua base (1000 ou 119 | 1024) quando o valor for menor que sua base, ou ja estejamos no ultimo 120 | elemento do array de sufixos, temos a melhor aproximação com o sufixo 121 | apropriado. */ 122 | for ( size_t i = 1; i < TOT_ELEMENTS_SUFIX; i++ ) 123 | { 124 | if ( ( bytes / base ) < base || i == ( TOT_ELEMENTS_SUFIX - 1 ) ) 125 | { 126 | double val = ( double ) bytes / base; 127 | 128 | sn = snprintf ( buffer, len_buff, "%.2f %s", val, sufix[i] ); 129 | return ( sn > 0 && ( size_t ) sn < len_buff ); 130 | } 131 | 132 | bytes /= base; 133 | } 134 | 135 | return false; /* unreached */ 136 | } 137 | -------------------------------------------------------------------------------- /src/human_readable.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef HUMAN_READABLE_H 22 | #define HUMAN_READABLE_H 23 | 24 | #include // bool type 25 | #include // uint*_t type 26 | #include // size_t type 27 | 28 | // prerequisite call this before usage human_readable 29 | void 30 | define_sufix ( const bool view_si, const bool view_bytes ); 31 | 32 | bool 33 | human_readable ( char *buffer, 34 | const size_t len_buff, 35 | const uint64_t bytes, 36 | int mode ); 37 | 38 | // modes human_readable 39 | enum mode 40 | { 41 | RATE = 1, // sufix/s 42 | TOTAL // sufix 43 | }; 44 | 45 | #endif // HUMAN_READABLE_H 46 | -------------------------------------------------------------------------------- /src/jhash.h: -------------------------------------------------------------------------------- 1 | #ifndef JHASH_H 2 | #define JHASH_H 3 | 4 | /* jhash.h: Jenkins hash support. 5 | * 6 | * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net) 7 | * 8 | * https://burtleburtle.net/bob/hash/ 9 | * 10 | * These are the credits from Bob's sources: 11 | * 12 | * lookup3.c, by Bob Jenkins, May 2006, Public Domain. 13 | * 14 | * These are functions for producing 32-bit hashes for hash table lookup. 15 | * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() 16 | * are externally useful functions. Routines to test the hash are included 17 | * if SELF_TEST is defined. You can use this free for any purpose. It's in 18 | * the public domain. It has no warranty. 19 | * 20 | * -- 21 | * Edited to useful to netproc 22 | * Copyright (C) 2022 Mayco S. Berghetti 23 | */ 24 | 25 | #include 26 | #include "macro_util.h" 27 | 28 | #define rot( x, k ) ( ( ( x ) << ( k ) ) | ( ( x ) >> ( 32 - ( k ) ) ) ) 29 | 30 | // clang-format off 31 | /* JHASH_MIX -- mix 3 32-bit values reversibly. */ 32 | #define JHASH_MIX(a, b, c) \ 33 | { \ 34 | a -= c; a ^= rot(c, 4); c += b; \ 35 | b -= a; b ^= rot(a, 6); a += c; \ 36 | c -= b; c ^= rot(b, 8); b += a; \ 37 | a -= c; a ^= rot(c, 16); c += b; \ 38 | b -= a; b ^= rot(a, 19); a += c; \ 39 | c -= b; c ^= rot(b, 4); b += a; \ 40 | } 41 | 42 | /* JHASH_FINAL - final mixing of 3 32-bit values (a,b,c) into c */ 43 | #define JHASH_FINAL(a, b, c) \ 44 | { \ 45 | c ^= b; c -= rot(b, 14); \ 46 | a ^= c; a -= rot(c, 11); \ 47 | b ^= a; b -= rot(a, 25); \ 48 | c ^= b; c -= rot(b, 16); \ 49 | a ^= c; a -= rot(c, 4); \ 50 | b ^= a; b -= rot(a, 14); \ 51 | c ^= b; c -= rot(b, 24); \ 52 | } 53 | 54 | /* An arbitrary initial parameter */ 55 | #define JHASH_INITVAL 0xDEADBEEF 56 | 57 | /* jhash8 - hash an arbitrary key 58 | * @k: sequence of bytes as key 59 | * @length: the length of the key 60 | * @initval: the previous hash, or an arbitray value 61 | * 62 | * The generic version, hashes an arbitrary sequence of bytes. 63 | * No alignment or length assumptions are made about the input key. 64 | * 65 | * Returns the hash value of the key. The result depends on endianness. 66 | */ 67 | static inline uint32_t 68 | jhash8 ( const void *key, uint32_t length, uint32_t initval ) 69 | { 70 | uint32_t a, b, c; 71 | const uint8_t *k = ( const uint8_t * ) key; 72 | 73 | /* Set up the internal state */ 74 | a = b = c = JHASH_INITVAL + length + initval; 75 | 76 | /* All but the last block: affect some 32 bits of (a,b,c) */ 77 | while ( length > 12 ) 78 | { 79 | a += *k; 80 | b += *( k + 4 ); 81 | c += *( k + 8 ); 82 | JHASH_MIX ( a, b, c ); 83 | length -= 12; 84 | k += 12; 85 | } 86 | 87 | /* Last block: affect all 32 bits of (c) */ 88 | switch ( length ) 89 | { 90 | case 12: c += ( uint32_t ) k[11] << 24; FALLTHROUGH; 91 | case 11: c += ( uint32_t ) k[10] << 16; FALLTHROUGH; 92 | case 10: c += ( uint32_t ) k[9] << 8; FALLTHROUGH; 93 | case 9: c += k[8]; FALLTHROUGH; 94 | case 8: b += ( uint32_t ) k[7] << 24; FALLTHROUGH; 95 | case 7: b += ( uint32_t ) k[6] << 16; FALLTHROUGH; 96 | case 6: b += ( uint32_t ) k[5] << 8; FALLTHROUGH; 97 | case 5: b += k[4]; FALLTHROUGH; 98 | case 4: a += ( uint32_t ) k[3] << 24; FALLTHROUGH; 99 | case 3: a += ( uint32_t ) k[2] << 16; FALLTHROUGH; 100 | case 2: a += ( uint32_t ) k[1] << 8; FALLTHROUGH; 101 | case 1: 102 | a += k[0]; 103 | JHASH_FINAL ( a, b, c ); 104 | } 105 | 106 | return c; 107 | } 108 | 109 | /* jhash32 - hash an array of uint32_t's 110 | * @k: the key which must be an array of uint32_t's 111 | * @length: the number of uint32_t's in the key 112 | * @initval: the previous hash, or an arbitray value 113 | * 114 | * Returns the hash value of the key. 115 | */ 116 | static inline uint32_t 117 | jhash32 ( const uint32_t *k, uint32_t length, uint32_t initval ) 118 | { 119 | uint32_t a, b, c; 120 | 121 | /* Set up the internal state */ 122 | a = b = c = JHASH_INITVAL + ( length << 2 ) + initval; 123 | 124 | /* Handle most of the key */ 125 | while ( length > 3 ) 126 | { 127 | a += k[0]; 128 | b += k[1]; 129 | c += k[2]; 130 | JHASH_MIX ( a, b, c ); 131 | length -= 3; 132 | k += 3; 133 | } 134 | 135 | /* Handle the last 3 uint32_t's */ 136 | switch ( length ) 137 | { 138 | case 3: c += k[2]; FALLTHROUGH; 139 | case 2: b += k[1]; FALLTHROUGH; 140 | case 1: 141 | a += k[0]; 142 | JHASH_FINAL ( a, b, c ); 143 | } 144 | 145 | return c; 146 | } 147 | 148 | // clang-format on 149 | #endif /* JHASH_H */ 150 | -------------------------------------------------------------------------------- /src/log.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // FILE 22 | #include // free 23 | #include 24 | #include 25 | 26 | #include "log.h" 27 | #include "vector.h" 28 | #include "human_readable.h" 29 | #include "m_error.h" 30 | 31 | struct log_processes 32 | { 33 | char *name; 34 | nstats_t tot_Bps_rx; // trafego total 35 | nstats_t tot_Bps_tx; 36 | }; 37 | 38 | static struct log_processes *log_processes = NULL; 39 | static size_t len_log_processes = 0; 40 | static FILE *file = NULL; 41 | 42 | // space justify column 43 | #define TAXA 14 44 | 45 | // TAXA + TAXA + PROGRAM + '\n' 46 | #define LEN_HEADER TAXA * 2 + 7 + 1 47 | 48 | static void 49 | write_process_to_file ( struct log_processes *processes, 50 | const size_t tot_process, 51 | FILE *file ) 52 | { 53 | char rx_tot[LEN_STR_TOTAL]; 54 | char tx_tot[LEN_STR_TOTAL]; 55 | 56 | for ( size_t i = 0; i < tot_process; i++ ) 57 | { 58 | // not log process whitout traffic 59 | if ( !processes[i].tot_Bps_rx && !processes[i].tot_Bps_tx ) 60 | continue; 61 | 62 | human_readable ( tx_tot, sizeof tx_tot, processes[i].tot_Bps_tx, TOTAL ); 63 | 64 | human_readable ( rx_tot, sizeof rx_tot, processes[i].tot_Bps_rx, TOTAL ); 65 | 66 | fprintf ( file, 67 | "%*s%*s%s\n", 68 | -TAXA, 69 | tx_tot, 70 | -TAXA, 71 | rx_tot, 72 | processes[i].name ); 73 | } 74 | } 75 | 76 | static char * 77 | copy_name ( const char *name, size_t size ) 78 | { 79 | char *p = malloc ( size + 1 ); 80 | 81 | if ( p ) 82 | { 83 | memcpy ( p, name, size ); 84 | p[size] = '\0'; 85 | } 86 | 87 | return p; 88 | } 89 | 90 | // percorre todos os processos e busca se um processo ( ou outro com mesmo nome, 91 | // assim podemos ter no arquivo de log, os dados total sobre um programa, 92 | // não apenas sobre uma execução do programa), 93 | // ja esta presente no buffer espelho do arquivo de log 94 | // se estiver present incrementa as estaticias de rede desse processo, caso não 95 | // adiciona ao buffer ( e consequentement sera exibido no arquivo de log) 96 | static bool 97 | update_log_process ( process_t **new_procs ) 98 | { 99 | while ( *new_procs ) 100 | { 101 | process_t *proc = *new_procs++; 102 | 103 | struct log_processes *log = log_processes; 104 | 105 | size_t j; 106 | for ( j = 0; j < len_log_processes; j++, log++ ) 107 | { 108 | if ( strcmp ( proc->name, log->name ) ) 109 | continue; 110 | 111 | log->tot_Bps_rx += proc->net_stat.bytes_last_sec_rx; 112 | log->tot_Bps_tx += proc->net_stat.bytes_last_sec_tx; 113 | 114 | // only one process with same name exist in this buffer 115 | break; 116 | } 117 | 118 | // not found, add new process in buffer 119 | if ( j == len_log_processes ) 120 | { 121 | log->name = copy_name ( proc->name, strlen ( proc->name ) ); 122 | if ( !log->name ) 123 | return false; 124 | 125 | log->tot_Bps_rx = proc->net_stat.tot_Bps_rx; 126 | log->tot_Bps_tx = proc->net_stat.tot_Bps_tx; 127 | len_log_processes++; 128 | 129 | if ( !vector_push ( log_processes, log ) ) 130 | return false; 131 | } 132 | } 133 | 134 | return true; 135 | } 136 | 137 | int 138 | log_init ( const char *path_log ) 139 | { 140 | file = fopen ( path_log, "w+" ); 141 | 142 | if ( !file ) 143 | { 144 | ERROR_DEBUG ( "Error open/create file '%s': %s", 145 | path_log, 146 | strerror ( errno ) ); 147 | return 0; 148 | } 149 | 150 | log_processes = vector_new ( sizeof ( struct log_processes ) ); 151 | 152 | if ( !log_processes ) 153 | { 154 | fclose ( file ); 155 | ERROR_DEBUG ( "%s", "Error create vector log processes" ); 156 | 157 | return 0; 158 | } 159 | 160 | fprintf ( file, 161 | "%*s%*s%s\n", 162 | -TAXA, 163 | "TOTAL TX", 164 | -TAXA, 165 | "TOTAL RX", 166 | "PROGRAM" ); 167 | 168 | return 1; 169 | } 170 | 171 | int 172 | log_file ( process_t **processes ) 173 | { 174 | if ( !update_log_process ( processes ) ) 175 | return 0; 176 | 177 | // set file one line below header 178 | fseek ( file, LEN_HEADER, SEEK_SET ); 179 | write_process_to_file ( log_processes, len_log_processes, file ); 180 | 181 | return 1; 182 | } 183 | 184 | void 185 | log_free ( void ) 186 | { 187 | if ( file ) 188 | fclose ( file ); 189 | 190 | if ( log_processes ) 191 | { 192 | for ( size_t i = 0; i < len_log_processes; i++ ) 193 | free ( log_processes[i].name ); 194 | 195 | vector_free ( log_processes ); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/log.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef LOG_FILE 22 | #define LOG_FILE 23 | 24 | #include "processes.h" 25 | #include "rate.h" 26 | 27 | int 28 | log_init ( const char *path_log ); 29 | 30 | int 31 | log_file ( process_t **processes ); 32 | 33 | void 34 | log_free ( void ); 35 | 36 | #endif // LOG_FILE 37 | -------------------------------------------------------------------------------- /src/m_error.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // va_* 22 | #include 23 | 24 | #define DEBUG "[DEBUG] " 25 | #define ERROR "[ERROR] " 26 | #define FATAL "[FATAL] " 27 | 28 | /* 29 | * vfprintf() in print() uses nonliteral format string. It may break 30 | * compilation if user enables corresponding warning. Disable it explicitly. 31 | */ 32 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 33 | 34 | static void 35 | print ( const char *restrict tag, const char *restrict fmt, va_list args ) 36 | { 37 | fprintf ( stderr, "%s", tag ); 38 | vfprintf ( stderr, fmt, args ); 39 | fprintf ( stderr, "\n" ); 40 | } 41 | 42 | void 43 | fatal_error ( const char *fmt, ... ) 44 | { 45 | va_list args; 46 | 47 | va_start ( args, fmt ); 48 | print ( FATAL, fmt, args ); 49 | va_end ( args ); 50 | } 51 | 52 | void 53 | debug_error ( const char *fmt, ... ) 54 | { 55 | va_list args; 56 | 57 | va_start ( args, fmt ); 58 | print ( DEBUG, fmt, args ); 59 | va_end ( args ); 60 | } 61 | -------------------------------------------------------------------------------- /src/m_error.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef ERROR_H 22 | #define ERROR_H 23 | 24 | #include // strerror 25 | #include // variable errno 26 | 27 | #ifdef NDEBUG 28 | #define ERROR_DEBUG( fmt, ... ) 29 | #else 30 | #define ERROR_DEBUG( fmt, ... ) \ 31 | do \ 32 | { \ 33 | debug_error ( "%s:%d - " fmt, __FILE__, __LINE__, __VA_ARGS__ ); \ 34 | } \ 35 | while ( 0 ) 36 | #endif 37 | 38 | // exibe mensagem na saida de erro padrão 39 | // e sai com EXIT_FAILURE 40 | void 41 | fatal_error ( const char *msg, ... ); 42 | 43 | void 44 | debug_error ( const char *msg, ... ); 45 | 46 | #endif // ERROR_H 47 | -------------------------------------------------------------------------------- /src/macro_util.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021-2022 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef MACRO_UTIL_H 22 | #define MACRO_UTIL_H 23 | 24 | #define MAX( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) ) 25 | 26 | #define ARRAY_SIZE( x ) ( sizeof ( x ) / sizeof ( x[0] ) ) 27 | 28 | #define SIZEOF_MEMBER( type, member ) ( sizeof ( ( ( type * ) 0 )->member ) ) 29 | 30 | #ifdef __GNUC__ 31 | #define UNUSED __attribute__ ( ( __unused__ ) ) 32 | #define FALLTHROUGH __attribute__ ( ( __fallthrough__ ) ) 33 | #else 34 | #define UNUSED( x ) 35 | #define FALLTHROUGH 36 | #endif 37 | 38 | #endif // MACRO_UTIL_H 39 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // sigaction 22 | #include // STDIN_FILENO 23 | #include // poll 24 | #include 25 | 26 | #include "config.h" 27 | #include "packet.h" 28 | #include "rate.h" 29 | #include "processes.h" 30 | #include "sock.h" 31 | #include "ring.h" 32 | #include "filter.h" 33 | #include "statistics.h" 34 | #include "human_readable.h" 35 | #include "timer.h" 36 | #include "tui.h" 37 | #include "log.h" 38 | #include "usage.h" 39 | #include "m_error.h" 40 | #include "resolver/resolver.h" 41 | #include "macro_util.h" 42 | 43 | // time to refresh in milliseconds 44 | #define T_REFRESH 1000 45 | 46 | static void 47 | config_sig_handler ( void ); 48 | 49 | // handled by function sig_handler 50 | static volatile sig_atomic_t prog_exit = 0; 51 | 52 | int 53 | main ( int argc, char **argv ) 54 | { 55 | setlocale ( LC_CTYPE, "" ); // needle to ncursesw 56 | 57 | struct ring *ring = NULL; 58 | struct processes *processes = NULL; 59 | 60 | struct config_op *co = parse_options ( argc, argv ); 61 | 62 | int sock = socket_init ( co->iface ); 63 | if ( sock == -1 ) 64 | { 65 | if ( getuid () ) 66 | fatal_error ( "Root is needed to running" ); 67 | else 68 | fatal_error ( "Error create socket: %s", strerror ( errno ) ); 69 | 70 | goto EXIT; 71 | } 72 | 73 | ring = ring_init ( sock ); 74 | if ( !ring ) 75 | { 76 | fatal_error ( "Error ring_init" ); 77 | goto EXIT; 78 | } 79 | 80 | // filter BPF 81 | if ( !filter_set ( sock, co->proto ) ) 82 | { 83 | fatal_error ( "Error set filter network" ); 84 | goto EXIT; 85 | } 86 | 87 | if ( co->log && !log_init ( co->path_log ) ) 88 | { 89 | fatal_error ( "Error log_init" ); 90 | goto EXIT; 91 | } 92 | 93 | processes = processes_init (); 94 | if ( !processes ) 95 | { 96 | fatal_error ( "Error process_init" ); 97 | goto EXIT; 98 | } 99 | 100 | if ( !connection_init () ) 101 | { 102 | fatal_error ( "Error connection_init" ); 103 | goto EXIT; 104 | } 105 | 106 | if ( co->view_conections && co->translate_host && !resolver_init ( 0, 0 ) ) 107 | { 108 | fatal_error ( "Error resolver_init" ); 109 | goto EXIT; 110 | } 111 | 112 | define_sufix ( co->view_si, co->view_bytes ); 113 | if ( !tui_init ( co ) ) 114 | { 115 | fatal_error ( "Error setup terminal user interface" ); 116 | goto EXIT; 117 | } 118 | 119 | config_sig_handler (); 120 | 121 | if ( !processes_update ( processes, co ) ) 122 | { 123 | fatal_error ( "Error get processes" ); 124 | goto EXIT; 125 | } 126 | 127 | uint32_t diff_time = 0; 128 | uint64_t cur_time = get_time (); 129 | if ( !cur_time ) 130 | { 131 | fatal_error ( "Error start timer" ); 132 | goto EXIT; 133 | } 134 | 135 | struct pollfd poll_set[2] = { 136 | { .fd = STDIN_FILENO, .events = POLLIN, .revents = 0 }, 137 | { .fd = sock, .events = POLLIN | POLLPRI, .revents = 0 } 138 | }; 139 | 140 | int block_num = 0; 141 | struct tpacket_block_desc *pbd; 142 | pbd = ( struct tpacket_block_desc * ) ring->rd[block_num].iov_base; 143 | 144 | bool need_update_processes = false; 145 | 146 | // main loop 147 | while ( !prog_exit ) 148 | { 149 | bool packtes_reads = false; 150 | 151 | // read all blocks availables 152 | while ( pbd->hdr.bh1.block_status & TP_STATUS_USER ) 153 | { 154 | struct tpacket3_hdr *ppd; 155 | 156 | ppd = ( struct tpacket3_hdr * ) ( ( uint8_t * ) pbd + 157 | pbd->hdr.bh1.offset_to_first_pkt ); 158 | 159 | // read all frames of block 160 | for ( size_t i = 0; i < pbd->hdr.bh1.num_pkts; i++, 161 | ppd = ( struct tpacket3_hdr * ) ( ( uint8_t * ) ppd + 162 | ppd->tp_next_offset ) ) 163 | { 164 | // se houver dados porem não foi possivel identificar o trafego, 165 | // não tem estatisticas para ser adicionada aos processos. 166 | // deve ser trafego de protocolo não suportado 167 | struct packet packet = { 0 }; 168 | if ( !parse_packet ( &packet, ppd ) ) 169 | continue; 170 | 171 | // se não for possivel identificar de qual processo o trafego 172 | // pertence é sinal que existe um novo processo, ou nova conexão 173 | // de um processo existente, que ainda não foi mapeado, então 174 | // anotamos que sera necessario atualizar a lista de processos 175 | // com conexões ativas. 176 | if ( !statistics_add ( &packet, co->view_conections ) ) 177 | { 178 | need_update_processes = true; 179 | continue; 180 | } 181 | 182 | packtes_reads = true; 183 | } 184 | 185 | // pass block controller to kernel 186 | pbd->hdr.bh1.block_status = TP_STATUS_KERNEL; 187 | 188 | // rotate block 189 | block_num = ( block_num + 1 ) % ring->req.tp_block_nr; 190 | pbd = ( struct tpacket_block_desc * ) ring->rd[block_num].iov_base; 191 | } 192 | 193 | if ( packtes_reads ) 194 | continue; 195 | 196 | int stop = 0; 197 | while ( !stop ) 198 | { 199 | int rp; 200 | do 201 | { 202 | errno = 0; 203 | rp = poll ( poll_set, 204 | ARRAY_SIZE ( poll_set ), 205 | T_REFRESH - diff_time ); 206 | } 207 | while ( errno == EINTR ); 208 | 209 | if ( rp == -1 ) 210 | { 211 | ERROR_DEBUG ( "poll: \"%s\"", strerror ( errno ) ); 212 | goto EXIT; 213 | } 214 | else if ( rp > 0 ) 215 | { 216 | for ( size_t i = 0; i < ARRAY_SIZE ( poll_set ); i++ ) 217 | { 218 | if ( !poll_set[i].revents ) 219 | continue; 220 | 221 | if ( poll_set[i].fd == STDIN_FILENO && 222 | tui_handle_input ( co ) == P_EXIT ) 223 | goto EXIT; 224 | 225 | if ( poll_set[i].fd == sock ) 226 | stop = 1; 227 | } 228 | } 229 | 230 | uint64_t new_time = get_time (); 231 | 232 | if ( new_time < cur_time ) 233 | continue; 234 | 235 | diff_time = new_time - cur_time; 236 | 237 | if ( diff_time >= T_REFRESH ) 238 | { 239 | co->running += diff_time; 240 | diff_time -= T_REFRESH; 241 | cur_time = new_time + diff_time; 242 | 243 | rate_calc ( processes, co ); 244 | 245 | tui_show ( processes, co ); 246 | 247 | if ( co->log && !log_file ( processes->proc ) ) 248 | { 249 | goto EXIT; 250 | } 251 | 252 | rate_update ( processes, co ); 253 | 254 | if ( need_update_processes ) 255 | { 256 | if ( !processes_update ( processes, co ) ) 257 | goto EXIT; 258 | 259 | need_update_processes = false; 260 | } 261 | } 262 | } 263 | 264 | } // main loop 265 | 266 | EXIT: 267 | 268 | socket_free ( sock ); 269 | ring_free ( ring ); 270 | log_free (); 271 | processes_free ( processes ); 272 | connection_free (); 273 | resolver_free (); 274 | tui_free (); 275 | 276 | return prog_exit; 277 | } 278 | 279 | static void 280 | sig_handler ( int sig ) 281 | { 282 | // "The return value of a simple command is its exit status, 283 | // or 128+n if the command is terminated by signal n" 284 | // by man bash 285 | prog_exit = 128 + sig; 286 | } 287 | 288 | static void 289 | config_sig_handler ( void ) 290 | { 291 | struct sigaction sigact = { .sa_handler = sig_handler }; 292 | 293 | sigaction ( SIGINT, &sigact, NULL ); 294 | sigaction ( SIGTERM, &sigact, NULL ); 295 | } 296 | -------------------------------------------------------------------------------- /src/packet.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef NETWORK_H 22 | #define NETWORK_H 23 | 24 | #include // types uint*_t 25 | #include // setsockopt 26 | #include // struct tpacket3_hdr 27 | 28 | #include "sockaddr.h" 29 | 30 | // used for function parse_packet e statistics 31 | struct packet 32 | { 33 | struct tuple tuple; // source and dest ip/port 34 | uint32_t lenght; // lenght of packet 35 | int if_index; // interface index 36 | uint8_t direction; // tx or rx 37 | }; 38 | 39 | // packet.direction 40 | #define PKT_DOWN 1 41 | #define PKT_UPL 2 42 | 43 | // preenche a struct packet com os dados do pacote recebido 44 | int 45 | parse_packet ( struct packet *pkt, struct tpacket3_hdr *ppd ); 46 | 47 | #endif // NETWORK_H 48 | -------------------------------------------------------------------------------- /src/pid.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // FILE* 22 | #include 23 | 24 | // this can even represent an unsigned integer (4294967295) 25 | #define MAX_DIGITS_UINT32 10 26 | 27 | #define PATH_MAX_PID "/proc/sys/kernel/pid_max" 28 | 29 | uint32_t 30 | get_max_digits_pid ( void ) 31 | { 32 | FILE *file = fopen ( PATH_MAX_PID, "r" ); 33 | if ( !file ) 34 | return MAX_DIGITS_UINT32; 35 | 36 | char max_pid[MAX_DIGITS_UINT32 + 1]; 37 | int match = fscanf ( file, "%10s", max_pid ); 38 | fclose ( file ); 39 | 40 | if ( 1 != match ) 41 | return MAX_DIGITS_UINT32; 42 | 43 | char *p = max_pid; 44 | while ( *p ) 45 | p++; 46 | 47 | return p - max_pid; 48 | } 49 | -------------------------------------------------------------------------------- /src/pid.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef PID_H 22 | #define PID_H 23 | 24 | uint32_t 25 | get_max_digits_pid ( void ); 26 | 27 | #endif // PID_H 28 | -------------------------------------------------------------------------------- /src/processes.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // variable errno 22 | #include // type boolean 23 | #include // snprintf 24 | #include // memset 25 | #include // readliink 26 | #include // open 27 | #include 28 | #include 29 | 30 | #include "processes.h" // process_t 31 | #include "jhash.h" 32 | #include "hashtable.h" 33 | #include "vector.h" 34 | #include "full_read.h" 35 | #include "config.h" 36 | #include "m_error.h" // ERROR_DEBUG 37 | #include "macro_util.h" 38 | 39 | // 4294967295 40 | #define LEN_MAX_INT 10 41 | 42 | // /proc/%d/cmdline 43 | #define MAX_CMDLINE 14 + LEN_MAX_INT 44 | 45 | // /proc//fd/ + 2 align 46 | #define MAX_PATH_FD 10 + LEN_MAX_INT + LEN_MAX_INT + 2 47 | 48 | // strlen ("socket:[4294967295]") + 5 align 49 | #define MAX_NAME_SOCKET 9 + LEN_MAX_INT + 5 50 | 51 | static hashtable_t *ht_process; 52 | 53 | static void 54 | handle_cmdline ( char *buff, size_t len ) 55 | { 56 | while ( --len ) 57 | { 58 | if ( *buff == '\0' || *buff == '\n' ) 59 | *buff = ' '; 60 | 61 | buff++; 62 | } 63 | 64 | // warranty, already null terminated 65 | *buff = '\0'; 66 | } 67 | 68 | // armazena o nome do processo no buffer e retorna 69 | // o tamanho do nome do processo ou -1 em caso de erro, 70 | // função cuida da alocação de memoria para o nome do processo 71 | static ssize_t 72 | get_name_process ( char **buffer, const pid_t pid ) 73 | { 74 | char path_cmdline[MAX_CMDLINE]; 75 | snprintf ( path_cmdline, sizeof ( path_cmdline ), "/proc/%d/cmdline", pid ); 76 | 77 | int fd = open ( path_cmdline, O_RDONLY ); 78 | if ( fd == -1 ) 79 | { 80 | ERROR_DEBUG ( "%s", strerror ( errno ) ); 81 | return -1; 82 | } 83 | 84 | ssize_t total_read = full_read ( fd, buffer ); 85 | close ( fd ); 86 | 87 | if ( total_read <= 0 ) 88 | { 89 | ERROR_DEBUG ( "%s", "error read process name" ); 90 | return -1; 91 | } 92 | 93 | handle_cmdline ( *buffer, ( size_t ) total_read ); 94 | 95 | // last bytes is null 96 | return total_read - 1; 97 | } 98 | 99 | static process_t * 100 | create_new_process ( pid_t pid ) 101 | { 102 | process_t *proc = malloc ( sizeof *proc ); 103 | 104 | if ( proc ) 105 | { 106 | proc->pid = pid; 107 | proc->active = true; 108 | 109 | proc->conections = vector_new ( sizeof ( connection_t * ) ); 110 | if ( !proc->conections ) 111 | goto ERROR; 112 | 113 | proc->total_conections = 0; 114 | if ( -1 == get_name_process ( &proc->name, pid ) ) 115 | goto ERROR; 116 | 117 | memset ( &proc->net_stat, 0, sizeof ( struct net_stat ) ); 118 | } 119 | 120 | return proc; 121 | 122 | ERROR: 123 | free ( proc ); 124 | return NULL; 125 | } 126 | 127 | static void 128 | free_process ( void *arg ) 129 | { 130 | process_t *process = arg; 131 | free ( process->name ); 132 | vector_free ( process->conections ); 133 | free ( process ); 134 | } 135 | 136 | static bool 137 | ht_cb_compare ( const void *key1, const void *key2 ) 138 | { 139 | return ( *( pid_t * ) key1 == *( pid_t * ) key2 ); 140 | } 141 | 142 | static hash_t 143 | ht_cb_hash ( const void *key ) 144 | { 145 | return jhash8 ( key, sizeof ( pid_t ), 0 ); 146 | } 147 | 148 | struct processes * 149 | processes_init ( void ) 150 | { 151 | struct processes *procs = calloc ( 1, sizeof *procs ); 152 | if ( !procs ) 153 | return NULL; 154 | 155 | procs->proc = vector_new ( sizeof ( process_t * ) ); 156 | 157 | ht_process = hashtable_new ( ht_cb_hash, ht_cb_compare, free_process ); 158 | if ( !ht_process ) 159 | { 160 | free ( procs ); 161 | return NULL; 162 | } 163 | 164 | return procs; 165 | } 166 | 167 | static int 168 | remove_dead_proc ( UNUSED hashtable_t *ht, void *value, UNUSED void *user_data ) 169 | { 170 | process_t *proc = value; 171 | if ( !proc->active ) 172 | { 173 | free_process ( proc ); 174 | return 1; 175 | } 176 | 177 | proc->active = false; 178 | return 0; 179 | } 180 | 181 | /* 182 | percorre todos os processos encontrados no diretório '/proc/', 183 | em cada processo encontrado armazena todos os file descriptors 184 | do processo - /proc/$id/fd - no buffer fds 185 | depois compara o link simbolico apontado pelo FD com 'socket:[inode]', 186 | sendo inode coletado do arquivo '/proc/net/tcp', caso a comparação seja igual, 187 | encontramos o processo que corresponde ao inode (conexão). 188 | */ 189 | int 190 | processes_update ( struct processes *procs, struct config_op *co ) 191 | { 192 | if ( !connection_update ( co->proto ) ) 193 | return 0; 194 | 195 | // TODO: check if type uint32_t is correct/safe 196 | uint32_t *pids = NULL; 197 | int total_process = get_numeric_directory ( &pids, "/proc/" ); 198 | 199 | if ( -1 == total_process ) 200 | return 0; 201 | 202 | hashtable_foreach_remove ( ht_process, remove_dead_proc, NULL ); 203 | vector_clear ( procs->proc ); 204 | 205 | uint32_t *fds = NULL; 206 | for ( int i = 0; i < total_process; i++ ) 207 | { 208 | char path_fd[MAX_PATH_FD]; 209 | pid_t pid = pids[i]; 210 | 211 | int ret_sn = 212 | snprintf ( path_fd, sizeof ( path_fd ), "/proc/%d/fd/", pid ); 213 | 214 | int total_fd_process = get_numeric_directory ( &fds, path_fd ); 215 | 216 | if ( -1 == total_fd_process ) 217 | continue; 218 | 219 | process_t *proc = hashtable_get ( ht_process, &pid ); 220 | 221 | if ( proc ) 222 | { 223 | proc->active = true; 224 | vector_clear ( proc->conections ); 225 | } 226 | 227 | for ( int j = 0; j < total_fd_process; j++ ) 228 | { 229 | // concat "/proc//fd/%d" 230 | snprintf ( path_fd + ret_sn, 231 | sizeof ( path_fd ) - ret_sn, 232 | "%d", 233 | fds[j] ); 234 | 235 | char data_fd[MAX_NAME_SOCKET]; 236 | ssize_t len_link = 237 | readlink ( path_fd, data_fd, sizeof ( data_fd ) - 1 ); 238 | 239 | if ( len_link == -1 ) 240 | continue; 241 | 242 | data_fd[len_link] = '\0'; 243 | 244 | unsigned long int inode; 245 | if ( 1 != sscanf ( data_fd, "socket:[%lu", &inode ) ) 246 | continue; 247 | 248 | connection_t *conn = connection_get_by_inode ( inode ); 249 | 250 | if ( !conn ) 251 | continue; 252 | 253 | if ( !proc ) 254 | { 255 | proc = create_new_process ( pid ); 256 | if ( !proc ) 257 | break; // no return error, check others processes 258 | 259 | hashtable_set ( ht_process, &proc->pid, proc ); 260 | } 261 | 262 | conn->proc = proc; 263 | vector_push ( proc->conections, &conn ); 264 | } 265 | 266 | if ( proc ) 267 | { 268 | proc->total_conections = vector_size ( proc->conections ); 269 | vector_push ( procs->proc, &proc ); 270 | } 271 | } 272 | 273 | free ( fds ); 274 | free ( pids ); 275 | 276 | procs->total = vector_size ( procs->proc ); 277 | 278 | return 1; 279 | } 280 | 281 | void 282 | processes_free ( struct processes *processes ) 283 | { 284 | if ( !processes ) 285 | return; 286 | 287 | // free ( processes->proc ); 288 | vector_free ( processes->proc ); 289 | free ( processes ); 290 | hashtable_destroy ( ht_process ); 291 | } 292 | -------------------------------------------------------------------------------- /src/processes.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef PROCESS_H 22 | #define PROCESS_H 23 | 24 | #include 25 | 26 | #include "config.h" 27 | #include "connection.h" 28 | #include "directory.h" 29 | #include "rate.h" 30 | 31 | typedef struct process 32 | { 33 | struct net_stat net_stat; // network statistics 34 | connection_t **conections; // connections of process 35 | char *name; // process name 36 | pid_t pid; // process pid 37 | uint32_t total_conections; // total process connections 38 | 39 | bool active; // check if processes is active in update of processes 40 | } process_t; 41 | 42 | struct processes 43 | { 44 | process_t **proc; 45 | size_t total; 46 | }; 47 | 48 | struct processes * 49 | processes_init ( void ); 50 | 51 | int 52 | processes_update ( struct processes *procs, struct config_op *co ); 53 | 54 | void 55 | processes_free ( struct processes *procs ); 56 | 57 | #endif // PROCESS_H 58 | -------------------------------------------------------------------------------- /src/rate.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #include "processes.h" 25 | #include "round.h" 26 | #include "rate.h" 27 | 28 | static void 29 | rate_net_stat ( struct net_stat *ns, bool view_bytes ) 30 | { 31 | uint64_t sum_bytes_rx = 0, sum_bytes_tx = 0, sum_pps_rx = 0, sum_pps_tx = 0; 32 | 33 | // sum all bytes and packets received and sent 34 | for ( int i = 0; i < SAMPLE_SPACE_SIZE; i++ ) 35 | { 36 | sum_bytes_rx += ns->Bps_rx[i]; 37 | sum_bytes_tx += ns->Bps_tx[i]; 38 | 39 | sum_pps_rx += ns->pps_rx[i]; 40 | sum_pps_tx += ns->pps_tx[i]; 41 | } 42 | 43 | // transform bytes to bits 44 | if ( !view_bytes ) 45 | { 46 | sum_bytes_rx *= 8; 47 | sum_bytes_tx *= 8; 48 | } 49 | 50 | // calc averege of bytes received / sent 51 | ns->avg_Bps_rx = m_round ( ( double ) sum_bytes_rx / SAMPLE_SPACE_SIZE ); 52 | ns->avg_Bps_tx = m_round ( ( double ) sum_bytes_tx / SAMPLE_SPACE_SIZE ); 53 | 54 | // calc averege of packets received / sent 55 | ns->avg_pps_rx = m_round ( ( double ) sum_pps_rx / SAMPLE_SPACE_SIZE ); 56 | ns->avg_pps_tx = m_round ( ( double ) sum_pps_tx / SAMPLE_SPACE_SIZE ); 57 | } 58 | 59 | void 60 | rate_calc ( struct processes *processes, const struct config_op *co ) 61 | { 62 | for ( size_t i = 0; i < processes->total; i++ ) 63 | { 64 | process_t *process = processes->proc[i]; 65 | 66 | rate_net_stat ( &process->net_stat, co->view_bytes ); 67 | 68 | // calc rate to each connection 69 | if ( co->view_conections ) 70 | { 71 | for ( size_t i = 0; i < process->total_conections; i++ ) 72 | rate_net_stat ( &process->conections[i]->net_stat, co->view_bytes ); 73 | } 74 | } 75 | } 76 | 77 | #define UPDATE_ID_BUFF( id ) ( ( id ) = ( ( id ) + 1 ) % SAMPLE_SPACE_SIZE ) 78 | 79 | static uint8_t idx_cir = 0; 80 | 81 | void 82 | rate_add_rx ( struct net_stat *ns, size_t lenght ) 83 | { 84 | ns->pps_rx[idx_cir]++; 85 | ns->Bps_rx[idx_cir] += lenght; 86 | 87 | ns->bytes_last_sec_rx += lenght; 88 | ns->tot_Bps_rx += lenght; 89 | } 90 | 91 | void 92 | rate_add_tx ( struct net_stat *ns, size_t lenght ) 93 | { 94 | ns->pps_tx[idx_cir]++; 95 | ns->Bps_tx[idx_cir] += lenght; 96 | 97 | ns->bytes_last_sec_tx += lenght; 98 | ns->tot_Bps_tx += lenght; 99 | } 100 | 101 | void 102 | rate_update ( struct processes *processes, const struct config_op *co ) 103 | { 104 | UPDATE_ID_BUFF ( idx_cir ); 105 | 106 | for ( size_t i = 0; i < processes->total; i++ ) 107 | { 108 | process_t *process = processes->proc[i]; 109 | 110 | process->net_stat.Bps_rx[idx_cir] = 0; 111 | process->net_stat.Bps_tx[idx_cir] = 0; 112 | process->net_stat.pps_rx[idx_cir] = 0; 113 | process->net_stat.pps_tx[idx_cir] = 0; 114 | 115 | process->net_stat.bytes_last_sec_rx = 0; 116 | process->net_stat.bytes_last_sec_tx = 0; 117 | 118 | // clear statistics of each connection alsa 119 | if ( co->view_conections ) 120 | { 121 | for ( size_t c = 0; c < process->total_conections; c++ ) 122 | { 123 | process->conections[c]->net_stat.Bps_rx[idx_cir] = 0; 124 | process->conections[c]->net_stat.Bps_tx[idx_cir] = 0; 125 | process->conections[c]->net_stat.pps_rx[idx_cir] = 0; 126 | process->conections[c]->net_stat.pps_tx[idx_cir] = 0; 127 | } 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/rate.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef RATE_H 22 | #define RATE_H 23 | 24 | #include // type size_t 25 | #include // uint*_t 26 | 27 | #include "config.h" 28 | 29 | /* amostral space, from last five seconds */ 30 | #define SAMPLE_SPACE_SIZE 5 31 | 32 | /* 33 | Considerando que a cada 1024 bits ou bytes (bits por segundo ou bytes por 34 | segundo), caso escolhido o padrão IEC com base 2, ou 1000 bits/bytes caso 35 | escolhido o padrão SI, com base 10, o valor sera dividido por 1000 ou 1024 36 | para que possa ser apresentado de forma "legivel por humanos", assim sempre 37 | teremos algo como: 1023 B/s, 1023.99 KB/s, 1023.99 Mib/s, 1023.99 Gib/s, ou 38 | 8388608 TiB/s (isso é um programa de rede, voltado para hosts e não 39 | roteadores dificilmente teremos trafego maior que isso...), então no pior 40 | caso teremos umas string com tamanhao de 14 bytes ja incluido null byte. */ 41 | #define LEN_STR_RATE 14 42 | 43 | // not ended with '/s' 44 | #define LEN_STR_TOTAL LEN_STR_RATE - 2 45 | 46 | typedef uint64_t nstats_t; 47 | 48 | struct net_stat 49 | { 50 | // samples pps and bytes per second rx/tx 51 | nstats_t pps_rx[SAMPLE_SPACE_SIZE]; 52 | nstats_t pps_tx[SAMPLE_SPACE_SIZE]; 53 | nstats_t Bps_rx[SAMPLE_SPACE_SIZE]; 54 | nstats_t Bps_tx[SAMPLE_SPACE_SIZE]; 55 | 56 | // averege bytes/second and packets/second rx/tx 57 | nstats_t avg_Bps_rx; 58 | nstats_t avg_Bps_tx; 59 | nstats_t avg_pps_rx; 60 | nstats_t avg_pps_tx; 61 | 62 | // total bytes traffic rx/tx 63 | nstats_t tot_Bps_rx; 64 | nstats_t tot_Bps_tx; 65 | 66 | // used by function log.c/log_file() 67 | nstats_t bytes_last_sec_rx; // total bytes in last second 68 | nstats_t bytes_last_sec_tx; 69 | }; 70 | 71 | struct processes; 72 | 73 | void 74 | rate_add_tx ( struct net_stat *ns, size_t lenght ); 75 | 76 | void 77 | rate_add_rx ( struct net_stat *ns, size_t lenght ); 78 | 79 | void 80 | rate_calc ( struct processes *processes, const struct config_op *co ); 81 | 82 | void 83 | rate_update ( struct processes *processes, const struct config_op *co ); 84 | 85 | #endif // RATE_H 86 | -------------------------------------------------------------------------------- /src/resolver/domain.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include // malloc, free 22 | #include // strncpy 23 | #include // getnameinfo 24 | #include // getnameinfo 25 | 26 | #include "domain.h" 27 | #include "thread_pool.h" 28 | #include "sock_util.h" // check_addr_equal 29 | #include "../jhash.h" 30 | #include "../hashtable.h" 31 | 32 | // (2048 * sizeof(struct host)) == ~2.31 MiB cache of domain 33 | #define DEFAULT_CACHE_SIZE 2048 34 | 35 | static hashtable_t *ht_hosts = NULL; 36 | static struct host **hosts = NULL; 37 | static size_t cache_size; 38 | 39 | static bool 40 | cb_ht_compare ( const void *key1, const void *key2 ) 41 | { 42 | return check_addr_equal ( ( union sockaddr_all * ) key1, 43 | ( union sockaddr_all * ) key2 ); 44 | } 45 | 46 | static hash_t 47 | cb_ht_hash ( const void *key ) 48 | { 49 | union sockaddr_all *addr = ( union sockaddr_all * ) key; 50 | 51 | switch ( addr->sa.sa_family ) 52 | { 53 | case AF_INET: 54 | return jhash32 ( ( uint32_t * ) &addr->in.sin_addr, 55 | sizeof ( addr->in.sin_addr ), 56 | 0 ); 57 | break; 58 | case AF_INET6: 59 | return jhash32 ( ( uint32_t * ) &addr->in6.sin6_addr, 60 | sizeof ( addr->in6.sin6_addr ), 61 | 0 ); 62 | break; 63 | default: 64 | return 0; 65 | } 66 | } 67 | 68 | int 69 | cache_domain_init ( unsigned int size ) 70 | { 71 | cache_size = ( size ) ? size : DEFAULT_CACHE_SIZE; 72 | hosts = calloc ( cache_size, sizeof ( struct host * ) ); 73 | 74 | if ( !hosts ) 75 | return 0; 76 | 77 | ht_hosts = hashtable_new ( cb_ht_hash, cb_ht_compare, free ); 78 | 79 | if ( !ht_hosts ) 80 | { 81 | free ( hosts ); 82 | return 0; 83 | } 84 | 85 | return 1; 86 | } 87 | 88 | // run on thread 89 | static void 90 | ip2domain_exec ( void *arg ) 91 | { 92 | struct host *host = ( struct host * ) arg; 93 | 94 | // convert ipv4 and ipv6 95 | // if error, convert to text ip same 96 | if ( getnameinfo ( &host->sa_all.sa, 97 | sizeof ( host->sa_all ), 98 | host->fqdn, 99 | sizeof ( host->fqdn ), 100 | NULL, 101 | 0, 102 | NI_DGRAM ) ) 103 | { 104 | sockaddr_ntop ( &host->sa_all, host->fqdn, sizeof ( host->fqdn ) ); 105 | } 106 | 107 | host->status = RESOLVED; 108 | } 109 | 110 | // return: 111 | // 1 name resolved 112 | // 0 name no resolved 113 | // -1 error 114 | int 115 | ip2domain ( union sockaddr_all *sa_all, char *buff, const size_t buff_len ) 116 | { 117 | struct host *host = hashtable_get ( ht_hosts, sa_all ); 118 | 119 | if ( host ) 120 | { 121 | if ( host->status == RESOLVED ) // cache hit 122 | { 123 | strncpy ( buff, host->fqdn, buff_len ); 124 | return 1; 125 | } 126 | else // resolving, thread working 127 | { 128 | sockaddr_ntop ( sa_all, buff, buff_len ); 129 | return 0; 130 | } 131 | } 132 | else // cache miss 133 | { 134 | sockaddr_ntop ( sa_all, buff, buff_len ); 135 | 136 | static size_t index = 0; 137 | 138 | if ( hosts[index] ) 139 | { 140 | if ( hosts[index]->status == RESOLVING ) 141 | return 0; 142 | 143 | hashtable_remove ( ht_hosts, &hosts[index]->sa_all ); 144 | } 145 | else 146 | { 147 | hosts[index] = malloc ( sizeof ( struct host ) ); 148 | 149 | if ( !hosts[index] ) 150 | return -1; 151 | } 152 | 153 | memcpy ( &hosts[index]->sa_all, sa_all, sizeof ( *sa_all ) ); 154 | hosts[index]->status = RESOLVING; 155 | 156 | // add task to workers (thread pool) 157 | add_task ( ip2domain_exec, hosts[index] ); 158 | 159 | hashtable_set ( ht_hosts, &hosts[index]->sa_all, hosts[index] ); 160 | 161 | index = ( index + 1 ) % cache_size; 162 | } 163 | 164 | return 0; 165 | } 166 | 167 | void 168 | cache_domain_free ( void ) 169 | { 170 | if ( !ht_hosts ) 171 | return; 172 | 173 | hashtable_destroy ( ht_hosts ); 174 | free ( hosts ); 175 | } 176 | -------------------------------------------------------------------------------- /src/resolver/domain.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef DOMAIN_H 21 | #define DOMAIN_H 22 | 23 | #include // NI_MAXHOST 24 | 25 | #include "../sockaddr.h" // union sockaddr_all 26 | 27 | struct host 28 | { 29 | union sockaddr_all sa_all; 30 | char fqdn[NI_MAXHOST]; 31 | int status; 32 | }; 33 | 34 | // host.status 35 | #define RESOLVED 1 36 | #define RESOLVING 2 37 | 38 | int 39 | cache_domain_init ( unsigned int size ); 40 | 41 | // retorna imediatamente o ip em formato de texto, porém na proxima requisição 42 | // irá retornar o dominio que estará em cache (se tudo der certo). 43 | // evitando a latencia que uma consulta DNS pode ter. 44 | int 45 | ip2domain ( union sockaddr_all *sa_all, char *buff, const size_t buff_len ); 46 | 47 | void 48 | cache_domain_free ( void ); 49 | 50 | #endif // DOMAIN_H 51 | -------------------------------------------------------------------------------- /src/resolver/get_cpu.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | // return tot cpu available on system or 0 23 | int 24 | get_count_cpu ( void ) 25 | { 26 | int ret = 0; 27 | 28 | // GNU extension 29 | #ifdef _SC_NPROCESSORS_ONLN 30 | ret = ( int ) sysconf ( _SC_NPROCESSORS_ONLN ); 31 | if ( ret < 0 ) 32 | ret = 0; 33 | #endif 34 | 35 | return ret; 36 | } 37 | -------------------------------------------------------------------------------- /src/resolver/get_cpu.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef GET_CPU_H 21 | #define GET_CPU_H 22 | 23 | int 24 | get_count_cpu ( void ); 25 | 26 | #endif // GET_CPU_H 27 | -------------------------------------------------------------------------------- /src/resolver/queue.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include // malloc 21 | #include "queue.h" 22 | 23 | struct queue_node 24 | { 25 | struct queue_node *next; 26 | void *data; 27 | }; 28 | 29 | struct queue 30 | { 31 | fclear clear; // callback user init 32 | struct queue_node *head; 33 | struct queue_node *tail; 34 | unsigned int size; 35 | }; 36 | 37 | static struct queue_node * 38 | create_element ( void *data ) 39 | { 40 | struct queue_node *e = malloc ( sizeof ( *e ) ); 41 | 42 | if ( e ) 43 | { 44 | e->data = data; 45 | e->next = NULL; 46 | } 47 | 48 | return e; 49 | } 50 | 51 | struct queue * 52 | queue_new ( fclear clear ) 53 | { 54 | struct queue *q = malloc ( sizeof *q ); 55 | 56 | if ( q ) 57 | { 58 | q->clear = clear; 59 | q->size = 0; 60 | } 61 | 62 | return q; 63 | } 64 | 65 | int 66 | enqueue ( struct queue *restrict queue, void *restrict data ) 67 | { 68 | struct queue_node *element = create_element ( data ); 69 | 70 | if ( !element ) 71 | return 0; 72 | 73 | if ( !queue->size ) 74 | queue->head = element; 75 | else 76 | queue->tail->next = element; 77 | 78 | queue->tail = element; 79 | 80 | queue->size++; 81 | return queue->size; 82 | } 83 | 84 | void * 85 | dequeue ( struct queue *queue ) 86 | { 87 | // empty queue 88 | if ( !queue->size ) 89 | return NULL; 90 | 91 | queue->size--; 92 | void *data = queue->head->data; 93 | struct queue_node *tmp = queue->head->next; 94 | 95 | free ( queue->head ); 96 | queue->head = tmp; 97 | 98 | return data; 99 | } 100 | 101 | void 102 | queue_destroy ( struct queue *queue ) 103 | { 104 | while ( queue->size ) 105 | { 106 | void *data = dequeue ( queue ); 107 | 108 | if ( queue->clear ) 109 | queue->clear ( data ); 110 | } 111 | 112 | free ( queue ); 113 | } 114 | 115 | unsigned int 116 | get_queue_size ( struct queue *queue ) 117 | { 118 | return queue->size; 119 | } 120 | -------------------------------------------------------------------------------- /src/resolver/queue.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef QUEUE_H 21 | #define QUEUE_H 22 | 23 | // Forward declaration 24 | struct queue; 25 | 26 | typedef void ( *fclear ) ( void * ); 27 | 28 | struct queue * 29 | queue_new ( fclear clear ); 30 | 31 | // returns 0 on failure and queue length on success 32 | int 33 | enqueue ( struct queue *queue, void *data ); 34 | 35 | // return NULL on failure 36 | void * 37 | dequeue ( struct queue *queue ); 38 | 39 | void 40 | queue_destroy ( struct queue *queue ); 41 | 42 | unsigned int 43 | get_queue_size ( struct queue *queue ); 44 | 45 | #endif // QUEUE_H 46 | -------------------------------------------------------------------------------- /src/resolver/resolver.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "thread_pool.h" 21 | #include "domain.h" 22 | 23 | int 24 | resolver_init ( unsigned int cache_size, unsigned int num_workers ) 25 | { 26 | if ( !thpool_init ( num_workers ) ) 27 | return 0; 28 | 29 | if ( !cache_domain_init ( cache_size ) ) 30 | return 0; 31 | 32 | return 1; 33 | } 34 | 35 | void 36 | resolver_free ( void ) 37 | { 38 | thpool_free (); 39 | cache_domain_free (); 40 | } 41 | -------------------------------------------------------------------------------- /src/resolver/resolver.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef RESOLVER_H 21 | #define RESOLVER_H 22 | 23 | // client include inly resolver.h 24 | #include "domain.h" 25 | #include "service.h" 26 | 27 | int 28 | resolver_init ( unsigned int cache_size, unsigned int num_workers ); 29 | 30 | void 31 | resolver_free ( void ); 32 | 33 | #endif // RESOLVER_H 34 | -------------------------------------------------------------------------------- /src/resolver/service.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include // strncpy 22 | #include // getservbyport 23 | #include // htons 24 | 25 | int 26 | port2serv ( unsigned short int port, 27 | const char *restrict proto, 28 | char *restrict buf, 29 | const size_t buf_len ) 30 | { 31 | struct servent *sve; 32 | 33 | sve = getservbyport ( htons ( port ), proto ); 34 | 35 | if ( sve != NULL ) 36 | { 37 | strncpy ( buf, sve->s_name, buf_len ); 38 | return 1; 39 | } 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /src/resolver/service.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef SERVICE_H 21 | #define SERVICE_H 22 | 23 | #include // size_t 24 | 25 | int 26 | port2serv ( unsigned short int port, 27 | const char *proto, 28 | char *buf, 29 | const size_t buf_len ); 30 | 31 | #endif // SERVICE_H 32 | -------------------------------------------------------------------------------- /src/resolver/sock_util.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2022 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include // size_t 22 | #include // memcmp 23 | #include // inet_ntop 24 | #include // struct sockaddr_storage 25 | 26 | #include "../sockaddr.h" 27 | 28 | bool 29 | check_addr_equal ( union sockaddr_all *addr1, union sockaddr_all *addr2 ) 30 | { 31 | if ( addr1->sa.sa_family == addr2->sa.sa_family ) 32 | { 33 | switch ( addr1->sa.sa_family ) 34 | { 35 | case AF_INET: 36 | return ( addr1->in.sin_addr.s_addr == addr2->in.sin_addr.s_addr ); 37 | case AF_INET6: 38 | return ( 0 == memcmp ( &addr1->in6.sin6_addr, 39 | &addr2->in6.sin6_addr, 40 | sizeof ( addr1->in6.sin6_addr ) ) ); 41 | } 42 | } 43 | 44 | return false; 45 | } 46 | 47 | void 48 | sockaddr_ntop ( union sockaddr_all *addr, char *buf, const size_t len_buff ) 49 | { 50 | switch ( addr->sa.sa_family ) 51 | { 52 | case AF_INET: 53 | inet_ntop ( AF_INET, &addr->in.sin_addr, buf, len_buff ); 54 | break; 55 | case AF_INET6: 56 | inet_ntop ( AF_INET6, &addr->in6.sin6_addr, buf, len_buff ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/resolver/sock_util.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2022 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef SOCK_UTIL_H 21 | #define SOCK_UTIL_H 22 | 23 | #include 24 | #include 25 | 26 | #include "../sockaddr.h" 27 | 28 | // return 1 if ip address is equal or 0 29 | bool 30 | check_addr_equal ( union sockaddr_all *addr1, union sockaddr_all *addr2 ); 31 | 32 | /* transform binary ip to text 33 | only to AF_INET and AF_INET6, 34 | len_buff must be enough to store a ip address of correspodent family */ 35 | void 36 | sockaddr_ntop ( union sockaddr_all *addr, char *buf, const size_t len_buff ); 37 | 38 | #endif // SOCK_UTIL_H 39 | -------------------------------------------------------------------------------- /src/resolver/thread_pool.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include // for malloc 21 | #include 22 | #include // for PTHREAD_STACK_MIN 23 | #include // sleep 24 | #include 25 | 26 | #include "queue.h" 27 | #include "get_cpu.h" 28 | 29 | #define DEFAULT_NUM_WORKERS 3 30 | 31 | struct bsem 32 | { 33 | pthread_mutex_t mutex; 34 | pthread_cond_t cond; 35 | bool value; 36 | }; 37 | 38 | struct task 39 | { 40 | void ( *func ) ( void * ); // function pointer 41 | void *args; // arg to function 42 | }; 43 | 44 | static struct bsem bsem_jobs = { .mutex = PTHREAD_MUTEX_INITIALIZER, 45 | .cond = PTHREAD_COND_INITIALIZER, 46 | .value = false }; 47 | 48 | static struct bsem bsem_exit = { .mutex = PTHREAD_MUTEX_INITIALIZER, 49 | .cond = PTHREAD_COND_INITIALIZER, 50 | .value = false }; 51 | 52 | static volatile bool worker_stop = false; 53 | 54 | static volatile unsigned int workers_alive = 0; 55 | static pthread_mutex_t mutex_workers_alive = PTHREAD_MUTEX_INITIALIZER; 56 | static pthread_mutex_t mutex_queue = PTHREAD_MUTEX_INITIALIZER; 57 | 58 | static struct queue *queue_task = NULL; 59 | 60 | static void 61 | bsem_post ( struct bsem *sem ) 62 | { 63 | pthread_mutex_lock ( &( sem->mutex ) ); 64 | sem->value = true; 65 | pthread_cond_signal ( &sem->cond ); 66 | pthread_mutex_unlock ( &( sem->mutex ) ); 67 | } 68 | 69 | static void 70 | bsem_post_all ( struct bsem *sem ) 71 | { 72 | pthread_mutex_lock ( &( sem->mutex ) ); 73 | sem->value = true; 74 | pthread_cond_broadcast ( &( sem->cond ) ); 75 | pthread_mutex_unlock ( &( sem->mutex ) ); 76 | } 77 | 78 | static void 79 | bsem_wait ( struct bsem *sem ) 80 | { 81 | pthread_mutex_lock ( &( sem->mutex ) ); 82 | while ( !sem->value ) 83 | pthread_cond_wait ( &sem->cond, &( sem->mutex ) ); 84 | 85 | sem->value = false; 86 | pthread_mutex_unlock ( &( sem->mutex ) ); 87 | } 88 | 89 | static struct task * 90 | create_task ( void ( *func ) ( void * ), void *args ) 91 | { 92 | struct task *task = malloc ( sizeof ( *task ) ); 93 | 94 | if ( task ) 95 | { 96 | task->func = func; 97 | task->args = args; 98 | } 99 | 100 | return task; 101 | } 102 | 103 | static void 104 | free_task ( struct task *task ) 105 | { 106 | free ( task ); 107 | } 108 | 109 | static void 110 | execute_task ( struct task *task ) 111 | { 112 | task->func ( task->args ); 113 | } 114 | 115 | static void * 116 | th_worker ( __attribute__ ( ( unused ) ) void *args ) 117 | { 118 | pthread_mutex_lock ( &mutex_workers_alive ); 119 | workers_alive++; 120 | pthread_mutex_unlock ( &mutex_workers_alive ); 121 | 122 | while ( !worker_stop ) 123 | { 124 | // wait for jobs 125 | bsem_wait ( &bsem_jobs ); 126 | 127 | if ( worker_stop ) 128 | break; 129 | 130 | pthread_mutex_lock ( &mutex_queue ); 131 | struct task *task = dequeue ( queue_task ); 132 | if ( get_queue_size ( queue_task ) ) 133 | bsem_post ( &bsem_jobs ); // rearm other thread 134 | pthread_mutex_unlock ( &mutex_queue ); 135 | 136 | if ( task ) 137 | { 138 | execute_task ( task ); 139 | free_task ( task ); 140 | } 141 | } 142 | 143 | pthread_mutex_lock ( &mutex_workers_alive ); 144 | workers_alive--; 145 | pthread_mutex_unlock ( &mutex_workers_alive ); 146 | 147 | // make up main thread to exit 148 | bsem_post ( &bsem_exit ); 149 | 150 | pthread_exit ( NULL ); 151 | } 152 | 153 | int 154 | thpool_init ( unsigned int num_workers ) 155 | { 156 | queue_task = queue_new ( free ); 157 | if ( !queue_task ) 158 | return 0; 159 | 160 | if ( !num_workers && !( num_workers = get_count_cpu () - 1 ) ) 161 | num_workers = DEFAULT_NUM_WORKERS; 162 | 163 | pthread_t tid; 164 | pthread_attr_t attr; 165 | 166 | pthread_attr_init ( &attr ); 167 | pthread_attr_setdetachstate ( &attr, PTHREAD_CREATE_DETACHED ); 168 | 169 | while ( num_workers-- ) 170 | { 171 | if ( pthread_create ( &tid, &attr, th_worker, NULL ) ) 172 | return 0; 173 | } 174 | 175 | pthread_attr_destroy ( &attr ); 176 | 177 | return 1; 178 | } 179 | 180 | int 181 | add_task ( void ( *func ) ( void * ), void *args ) 182 | { 183 | struct task *task = create_task ( func, args ); 184 | if ( !task ) 185 | return 0; 186 | 187 | // push job in queue 188 | pthread_mutex_lock ( &mutex_queue ); 189 | if ( !enqueue ( queue_task, task ) ) 190 | { 191 | free_task ( task ); 192 | pthread_mutex_unlock ( &mutex_queue ); 193 | return 0; 194 | } 195 | 196 | // wake up a thread to work 197 | bsem_post ( &bsem_jobs ); 198 | pthread_mutex_unlock ( &mutex_queue ); 199 | 200 | return 1; 201 | } 202 | 203 | void 204 | thpool_free ( void ) 205 | { 206 | worker_stop = true; 207 | 208 | int wait = DEFAULT_NUM_WORKERS; 209 | while ( workers_alive && wait-- ) 210 | { 211 | bsem_post_all ( &bsem_jobs ); 212 | bsem_wait ( &bsem_exit ); 213 | } 214 | 215 | if ( queue_task ) 216 | { 217 | pthread_mutex_lock ( &mutex_queue ); 218 | queue_destroy ( queue_task ); 219 | pthread_mutex_unlock ( &mutex_queue ); 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/resolver/thread_pool.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef THREAD_POLL_H 21 | #define THREAD_POLL_H 22 | 23 | /* all functions that return int, return 0 on failure and 1 on sucess */ 24 | 25 | int 26 | thpool_init ( unsigned int num_workers ); 27 | 28 | int 29 | add_task ( void ( *func ) ( void * ), void *args ); 30 | 31 | void 32 | thpool_free ( void ); 33 | 34 | #endif // THREAD_POLL_H 35 | -------------------------------------------------------------------------------- /src/ring.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // calloc 22 | #include 23 | #include // setsockopt 24 | #include // *PACKET* 25 | #include // ETH_HLEN 26 | #include // mmap 27 | #include // sysconf 28 | 29 | #include "ring.h" 30 | #include "m_error.h" 31 | 32 | // reference 33 | // https://www.kernel.org/doc/html/latest/networking/packet_mmap.html 34 | 35 | #ifndef TPACKET3_HDRLEN 36 | #error "TPACKET_V3 is necessary, check kernel linux version" 37 | #endif 38 | 39 | // each block will have at least 256KiB of size, because 128 * 2048 = 256KiB 40 | // this considering a page size of 4096. 41 | // this conf influences the use of CPU time and mmemory usage 42 | // keep it as power-of-two 43 | 44 | // quantidade de blocos 45 | #define N_BLOCKS 4 46 | 47 | #define FRAMES_PER_BLOCK 128 48 | // size of frame (packet), considering overhead of struct tpacket (80 bytes) 49 | // size small cause more usage CPU 50 | #define LEN_FRAME 2048 51 | 52 | // timeout in miliseconds 53 | // zero means that the kernel will calculate the timeout 54 | // https://github.com/torvalds/linux/blob/master/net/packet/af_packet.c#L596 55 | #define TIMEOUT_FRAME 0 56 | 57 | static int 58 | create_ring_buff ( struct ring *ring ) 59 | { 60 | long page_size; 61 | size_t frames_per_block; 62 | 63 | ring->req.tp_frame_size = LEN_FRAME; 64 | // TPACKET_ALIGN ( TPACKET3_HDRLEN ) + TPACKET_ALIGN ( LEN_FRAME ); 65 | 66 | // tamanho inicial de uma pagina de memoria 67 | errno = 0; 68 | if ( -1 == ( page_size = sysconf ( _SC_PAGESIZE ) ) ) 69 | { 70 | ERROR_DEBUG ( "%s", ( errno ? strerror ( errno ) : "Error sysconf" ) ); 71 | return 0; 72 | } 73 | 74 | // The block has to be page size aligned 75 | // dobra o tamanho do bloco até que caiba a quantidade de frames 76 | ring->req.tp_block_size = page_size; 77 | while ( ring->req.tp_block_size < ring->req.tp_frame_size * FRAMES_PER_BLOCK ) 78 | { 79 | ring->req.tp_block_size <<= 1; 80 | } 81 | 82 | ring->req.tp_block_nr = N_BLOCKS; 83 | frames_per_block = ring->req.tp_block_size / ring->req.tp_frame_size; 84 | ring->req.tp_frame_nr = ring->req.tp_block_nr * frames_per_block; 85 | ring->req.tp_retire_blk_tov = TIMEOUT_FRAME; 86 | 87 | ring->req.tp_feature_req_word = 0; 88 | ring->req.tp_sizeof_priv = 0; 89 | 90 | return 1; 91 | } 92 | 93 | static int 94 | config_ring ( int sock, struct ring *ring, int version ) 95 | { 96 | // set version TPACKET 97 | if ( setsockopt ( sock, 98 | SOL_PACKET, 99 | PACKET_VERSION, 100 | &version, 101 | sizeof ( version ) ) == -1 ) 102 | { 103 | ERROR_DEBUG ( "%s", strerror ( errno ) ); 104 | return 0; 105 | } 106 | 107 | // set conf buffer tpacket 108 | if ( setsockopt ( sock, 109 | SOL_PACKET, 110 | PACKET_RX_RING, 111 | &ring->req, 112 | sizeof ( ring->req ) ) == -1 ) 113 | { 114 | ERROR_DEBUG ( "%s", strerror ( errno ) ); 115 | return 0; 116 | } 117 | 118 | return 1; 119 | } 120 | 121 | static int 122 | map_buff ( int sock, struct ring *ring ) 123 | { 124 | size_t rx_ring_size = ring->req.tp_block_nr * ring->req.tp_block_size; 125 | ring->map = 126 | mmap ( 0, rx_ring_size, PROT_READ | PROT_WRITE, MAP_SHARED, sock, 0 ); 127 | 128 | if ( ring->map == MAP_FAILED ) 129 | { 130 | ERROR_DEBUG ( "%s", strerror ( errno ) ); 131 | return 0; 132 | } 133 | 134 | ring->rd = calloc ( ring->req.tp_block_nr, sizeof ( *ring->rd ) ); 135 | if ( !ring->rd ) 136 | { 137 | ERROR_DEBUG ( "%s", strerror ( errno ) ); 138 | return 0; 139 | } 140 | 141 | for ( size_t i = 0; i < ring->req.tp_block_nr; ++i ) 142 | { 143 | ring->rd[i].iov_base = ring->map + ( i * ring->req.tp_block_size ); 144 | ring->rd[i].iov_len = ring->req.tp_block_size; 145 | } 146 | 147 | return 1; 148 | } 149 | 150 | struct ring * 151 | ring_init ( int sock ) 152 | { 153 | struct ring *ring = malloc ( sizeof *ring ); 154 | 155 | if ( ring ) 156 | { 157 | if ( !create_ring_buff ( ring ) ) 158 | goto ERROR_EXIT; 159 | 160 | if ( !config_ring ( sock, ring, TPACKET_V3 ) ) 161 | goto ERROR_EXIT; 162 | 163 | if ( !map_buff ( sock, ring ) ) 164 | goto ERROR_EXIT; 165 | } 166 | 167 | return ring; 168 | 169 | ERROR_EXIT: 170 | free ( ring ); 171 | return NULL; 172 | } 173 | 174 | void 175 | ring_free ( struct ring *ring ) 176 | { 177 | if ( !ring ) 178 | return; 179 | 180 | munmap ( ring->map, ring->req.tp_block_size * ring->req.tp_block_nr ); 181 | free ( ring->rd ); 182 | free ( ring ); 183 | } 184 | -------------------------------------------------------------------------------- /src/ring.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef RING_H 22 | #define RING_H 23 | 24 | #include // struct iovec 25 | #include // strct tpacket_req3 26 | 27 | struct ring 28 | { 29 | struct tpacket_req3 req; 30 | struct iovec *rd; 31 | uint8_t *map; 32 | }; 33 | 34 | struct ring * 35 | ring_init ( int sock ); 36 | 37 | void 38 | ring_free ( struct ring *ring ); 39 | 40 | #endif // RING_H 41 | -------------------------------------------------------------------------------- /src/round.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | // based in https://www.codeproject.com/Articles/58289/C-Round-Function 24 | 25 | /* input never is negative here then 26 | we not verify number negative for more performance 27 | 28 | examples: 29 | input 1.1 - output 1 30 | input 1.4 - output 1 31 | input 1.5 - output 2 32 | input 1.9 - output 2 */ 33 | uint64_t 34 | m_round ( double number ) 35 | { 36 | return ( uint64_t ) ( number + 0.5 ); 37 | } 38 | -------------------------------------------------------------------------------- /src/round.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef M_ROUND_H 22 | #define M_ROUND_H 23 | 24 | #include 25 | 26 | uint64_t 27 | m_round ( double number ); 28 | 29 | #endif // M_ROUND_H 30 | -------------------------------------------------------------------------------- /src/slist.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef SLIST_H 22 | #define SLIST_H 23 | 24 | typedef struct slist_item 25 | { 26 | struct slist_item *next; 27 | } slist_item_t; 28 | 29 | typedef struct slist 30 | { 31 | slist_item_t *head; 32 | } slist_t; 33 | 34 | static inline void 35 | slist_preprend ( slist_t *list, slist_item_t *item ) 36 | { 37 | item->next = list->head; 38 | list->head = item; 39 | } 40 | 41 | static void 42 | slist_remove ( slist_t *list, slist_item_t *previous, slist_item_t *item ) 43 | { 44 | if ( previous ) 45 | previous->next = item->next; 46 | else 47 | list->head = item->next; 48 | } 49 | 50 | #endif // SLIST_H 51 | -------------------------------------------------------------------------------- /src/sock.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // malloc 22 | #include // htons 23 | #include // variable errno 24 | #include // defined ETH_P_ALL 25 | #include // struct sockaddr_ll 26 | #include // if_nametoindex 27 | #include // strerror 28 | #include // socket 29 | #include // socket 30 | #include // fcntl 31 | #include // close 32 | 33 | #include "sock.h" 34 | #include "m_error.h" 35 | 36 | static int 37 | socket_setnonblocking ( int sock ) 38 | { 39 | int flag; 40 | 41 | if ( ( flag = fcntl ( sock, F_GETFL ) ) == -1 ) 42 | { 43 | ERROR_DEBUG ( "Cannot get socket flags: \"%s\"", strerror ( errno ) ); 44 | return 0; 45 | } 46 | 47 | if ( fcntl ( sock, F_SETFL, flag | O_NONBLOCK ) == -1 ) 48 | { 49 | ERROR_DEBUG ( "Cannot set socket to non-blocking mode: \"%s\"", 50 | strerror ( errno ) ); 51 | return 0; 52 | } 53 | 54 | return 1; 55 | } 56 | 57 | static int 58 | bind_interface ( int sock, const char *iface ) 59 | { 60 | struct sockaddr_ll sock_ll = { 61 | .sll_family = AF_PACKET, 62 | .sll_protocol = htons ( ETH_P_ALL ), 63 | .sll_ifindex = 0 // explicit 0 match all interfaces 64 | }; 65 | 66 | if ( iface ) 67 | { 68 | if ( !( sock_ll.sll_ifindex = if_nametoindex ( iface ) ) ) 69 | { 70 | ERROR_DEBUG ( "%s", strerror ( errno ) ); 71 | return 0; 72 | } 73 | } 74 | 75 | if ( bind ( sock, ( struct sockaddr * ) &sock_ll, sizeof ( sock_ll ) ) == -1 ) 76 | { 77 | ERROR_DEBUG ( "Error bind interface %s", strerror ( errno ) ); 78 | return 0; 79 | } 80 | 81 | return 1; 82 | } 83 | 84 | int 85 | socket_init ( const char *iface ) 86 | { 87 | int sock; 88 | 89 | if ( ( sock = socket ( AF_PACKET, SOCK_RAW, htons ( ETH_P_ALL ) ) ) == -1 ) 90 | { 91 | ERROR_DEBUG ( "Error create socket: %s", strerror ( errno ) ); 92 | return -1; 93 | } 94 | 95 | if ( !socket_setnonblocking ( sock ) ) 96 | goto ERROR_EXIT; 97 | 98 | if ( !bind_interface ( sock, iface ) ) 99 | goto ERROR_EXIT; 100 | 101 | return sock; 102 | 103 | ERROR_EXIT: 104 | 105 | close ( sock ); 106 | return -1; 107 | } 108 | 109 | void 110 | socket_free ( int sock ) 111 | { 112 | if ( sock > 0 ) 113 | close ( sock ); 114 | } 115 | -------------------------------------------------------------------------------- /src/sock.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef SOCK_SNIFF_H 22 | #define SOCK_SNIFF_H 23 | 24 | #include "config.h" 25 | 26 | int 27 | socket_init ( const char *iface ); 28 | 29 | void 30 | socket_free ( int sock ); 31 | 32 | #endif // SOCK_SNIFF_H 33 | -------------------------------------------------------------------------------- /src/sockaddr.h: -------------------------------------------------------------------------------- 1 | #ifndef SOCKADDR_H 2 | #define SOCKADDR_H 3 | 4 | #include 5 | #include // struct sockaddr 6 | #include // struct sockaddr_in sockaddr_in6 7 | 8 | // information network layer 9 | union inet_all 10 | { 11 | uint32_t all[4]; 12 | uint32_t ip; 13 | uint32_t ip6[4]; 14 | struct in_addr in; 15 | struct in6_addr in6; 16 | }; 17 | 18 | struct layer3 19 | { 20 | union inet_all local; 21 | union inet_all remote; 22 | // uint16_t l3_proto; // ipv4 or ipv6 23 | }; 24 | 25 | // information transport layer (only port) 26 | struct layer4 27 | { 28 | uint16_t local_port; 29 | uint16_t remote_port; 30 | uint8_t protocol; // l4 protocol number (e.g 6 to TCP or 17 to UDP) 31 | }; 32 | 33 | // typle identify a connection ip:port <-> ip:port 34 | struct tuple 35 | { 36 | struct layer3 l3; 37 | struct layer4 l4; 38 | }; 39 | 40 | union sockaddr_all 41 | { 42 | struct sockaddr sa; 43 | struct sockaddr_in in; 44 | struct sockaddr_in6 in6; 45 | }; 46 | 47 | #endif // SOCKADDR_H 48 | -------------------------------------------------------------------------------- /src/sort.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #define _GNU_SOURCE // qsort_r 22 | #include 23 | #include 24 | 25 | #include "processes.h" 26 | #include "connection.h" 27 | #include "sort.h" 28 | 29 | static int 30 | compare_process ( const void *restrict p1, 31 | const void *restrict p2, 32 | void *restrict mode ) 33 | { 34 | process_t *proc1 = *( process_t ** ) p1; 35 | process_t *proc2 = *( process_t ** ) p2; 36 | 37 | int64_t r; 38 | switch ( *( int * ) mode ) 39 | { 40 | case RATE_RX: 41 | r = proc2->net_stat.avg_Bps_rx - proc1->net_stat.avg_Bps_rx; 42 | break; 43 | case RATE_TX: 44 | r = proc2->net_stat.avg_Bps_tx - proc1->net_stat.avg_Bps_tx; 45 | break; 46 | case TOT_RX: 47 | r = proc2->net_stat.tot_Bps_rx - proc1->net_stat.tot_Bps_rx; 48 | break; 49 | case TOT_TX: 50 | r = proc2->net_stat.tot_Bps_tx - proc1->net_stat.tot_Bps_tx; 51 | break; 52 | case PPS_RX: 53 | r = proc2->net_stat.avg_pps_rx - proc1->net_stat.avg_pps_rx; 54 | break; 55 | case PPS_TX: 56 | r = proc2->net_stat.avg_pps_tx - proc1->net_stat.avg_pps_tx; 57 | break; 58 | 59 | // PID 60 | default: 61 | r = proc1->pid - proc2->pid; 62 | } 63 | 64 | return ( r > 0 ) - ( r < 0 ); 65 | } 66 | 67 | static int 68 | compare_connection ( const void *restrict p1, 69 | const void *restrict p2, 70 | void *restrict mode ) 71 | { 72 | connection_t *con1 = *( connection_t ** ) p1; 73 | connection_t *con2 = *( connection_t ** ) p2; 74 | 75 | int64_t r; 76 | switch ( *( int * ) mode ) 77 | { 78 | case RATE_TX: 79 | r = con2->net_stat.avg_Bps_tx - con1->net_stat.avg_Bps_tx; 80 | break; 81 | case PPS_RX: 82 | r = con2->net_stat.avg_pps_rx - con1->net_stat.avg_pps_rx; 83 | break; 84 | case PPS_TX: 85 | r = con2->net_stat.avg_pps_tx - con1->net_stat.avg_pps_tx; 86 | break; 87 | 88 | // RATE RX 89 | default: 90 | r = con2->net_stat.avg_Bps_rx - con1->net_stat.avg_Bps_rx; 91 | } 92 | 93 | return ( r > 0 ) - ( r < 0 ); 94 | } 95 | 96 | void 97 | sort ( process_t **proc, 98 | size_t tot_process, 99 | int mode, 100 | const struct config_op *co ) 101 | { 102 | qsort_r ( proc, 103 | tot_process, 104 | sizeof ( process_t * ), 105 | compare_process, 106 | ( void * ) &mode ); 107 | 108 | if ( co->view_conections ) 109 | for ( size_t i = 0; i < tot_process; i++ ) 110 | qsort_r ( proc[i]->conections, 111 | proc[i]->total_conections, 112 | sizeof ( connection_t * ), 113 | compare_connection, 114 | ( void * ) &mode ); 115 | } 116 | -------------------------------------------------------------------------------- /src/sort.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef SORT_H 22 | #define SORT_H 23 | 24 | #include 25 | #include "processes.h" 26 | #include "connection.h" 27 | 28 | enum cols_sort 29 | { 30 | S_PID = 0, 31 | PPS_TX, 32 | PPS_RX, 33 | RATE_TX, 34 | RATE_RX, 35 | TOT_TX, 36 | TOT_RX, 37 | COLS_TO_SORT // total elements in enum 38 | }; 39 | 40 | void 41 | sort ( process_t **proc, 42 | size_t tot_process, 43 | int mode, 44 | const struct config_op *co ); 45 | 46 | #endif // SORT_H 47 | -------------------------------------------------------------------------------- /src/statistics.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include // IPPROTO_TCP, IPPROTO_UDP 24 | #include // TCP_ESTABLISHED, TCP_TIME_WAIT... 25 | 26 | #include "config.h" 27 | #include "packet.h" 28 | #include "rate.h" 29 | #include "processes.h" 30 | 31 | // static bool 32 | // conection_match_packet ( connection_t *conection, const struct packet *pkt ) 33 | // { 34 | // if ( conection->protocol != pkt->protocol ) 35 | // return false; 36 | // 37 | // // TCP must correspond exactly with the packet, if not, skip 38 | // if ( pkt->protocol == IPPROTO_TCP && 39 | // ( conection->local_port != pkt->local_port || 40 | // conection->remote_port != pkt->remote_port || 41 | // conection->remote_address != pkt->remote_address ) ) 42 | // { 43 | // return false; 44 | // } 45 | // 46 | // if ( pkt->protocol == IPPROTO_UDP ) 47 | // { 48 | // // the local port is the only parameter that the kernel exports 49 | // // in certain UDP situations (like a torrent), 50 | // // if that is different, skip 51 | // if ( conection->local_port != pkt->local_port ) 52 | // return false; 53 | // 54 | // // UDP connections with state TCP_ESTABLISHED must 55 | // // correspond exactly with the packet, if not, skip 56 | // else if ( conection->state == TCP_ESTABLISHED && 57 | // ( conection->remote_port != pkt->remote_port || 58 | // conection->remote_address != pkt->remote_address ) ) 59 | // return false; 60 | // 61 | // // udp connections have no state, however the kernel tries 62 | // // to correlate udp packets into connections, when it is able 63 | // // to assign the virtual state TCP_ESTABLISHED, when it is 64 | // // unable to assign the state TCP_CLOSE, and it ends up not 65 | // // exporting some data in /proc/net/udp, but we can "retrieve" 66 | // // that information from the captured packet 67 | // if ( conection->state == TCP_CLOSE ) 68 | // { 69 | // conection->local_address = pkt->local_address; 70 | // conection->remote_address = pkt->remote_address; 71 | // conection->remote_port = pkt->remote_port; 72 | // } 73 | // } 74 | // 75 | // return true; 76 | // } 77 | 78 | // static bool 79 | // check_udp( struct tuple *tp1, struct tuple *tp2 ) 80 | // { 81 | // if ( ( tp1->l4.remote_port != tp2->l4.remote_port || 82 | // tp1->l3.remote.ip != tp2->l3.remote.ip ) ) 83 | // return false; 84 | // 85 | // } 86 | 87 | bool 88 | statistics_add ( const struct packet *pkt, bool view_conections ) 89 | { 90 | connection_t *conn; 91 | 92 | conn = connection_get_by_tuple ( ( struct tuple * ) &pkt->tuple ); 93 | 94 | if ( conn ) 95 | { 96 | process_t *proc = conn->proc; 97 | 98 | /* connection was added but at the time of associating to a process 99 | the process had already been closed (probably) */ 100 | if ( !proc ) 101 | return false; 102 | 103 | conn->if_index = pkt->if_index; 104 | 105 | switch ( pkt->direction ) 106 | { 107 | case PKT_DOWN: 108 | rate_add_rx ( &proc->net_stat, pkt->lenght ); 109 | 110 | if ( view_conections ) 111 | rate_add_rx ( &conn->net_stat, pkt->lenght ); 112 | 113 | break; 114 | case PKT_UPL: 115 | rate_add_tx ( &proc->net_stat, pkt->lenght ); 116 | 117 | if ( view_conections ) 118 | rate_add_tx ( &conn->net_stat, pkt->lenght ); 119 | } 120 | 121 | return true; 122 | } 123 | 124 | return false; 125 | } 126 | -------------------------------------------------------------------------------- /src/statistics.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef STATISTICS_PROC_H 22 | #define STATISTICS_PROC_H 23 | 24 | #include 25 | 26 | #include "config.h" 27 | #include "processes.h" 28 | 29 | /* find process that belongs the connection and update statistics of network */ 30 | bool 31 | statistics_add ( const struct packet *pkt, bool view_conections ); 32 | 33 | #endif // STATISTICS_PROC_H 34 | -------------------------------------------------------------------------------- /src/str.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // type ssize_t 22 | #include // strrchr 23 | 24 | size_t 25 | strlen_space ( const char *str ) 26 | { 27 | char *p = strchr ( str, ' ' ); 28 | if ( p ) 29 | return p - str; 30 | 31 | return strlen ( str ); 32 | } 33 | 34 | ssize_t 35 | index_last_char ( const char *str, const int ch ) 36 | { 37 | char *p = strrchr ( str, ch ); 38 | if ( p ) 39 | return p - str; 40 | 41 | // not found 42 | return -1; 43 | } 44 | -------------------------------------------------------------------------------- /src/str.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef STR_H 22 | #define STR_H 23 | 24 | #include // type size_t 25 | 26 | // returns string length up to null byte or space, which comes first 27 | size_t 28 | strlen_space ( const char *string ); 29 | 30 | // return position of last occurrence of character in string 31 | ssize_t 32 | index_last_char ( const char *str, const int ch ); 33 | 34 | #endif // STR_H 35 | -------------------------------------------------------------------------------- /src/timer.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include // struct timespec 25 | 26 | // return current time in milliseconds 27 | uint64_t 28 | get_time ( void ) 29 | { 30 | clockid_t ci; 31 | 32 | #ifdef CLOCK_MONOTONIC_COARSE 33 | ci = CLOCK_MONOTONIC_COARSE; 34 | #else 35 | ci = CLOCK_MONOTONIC; 36 | #endif 37 | 38 | struct timespec ts; 39 | if ( -1 == clock_gettime ( ci, &ts ) ) 40 | return 0; 41 | 42 | return ts.tv_sec * 1000U + ts.tv_nsec / 1000000UL; 43 | } 44 | 45 | // hh:mm:ss 46 | #define LEN_BUFF_CLOCK 14 47 | 48 | char * 49 | msec2clock ( uint64_t milliseconds ) 50 | { 51 | static char clock[LEN_BUFF_CLOCK]; 52 | 53 | uint32_t secs = milliseconds / 1000U; 54 | 55 | uint32_t hours, seconds, minutes; 56 | 57 | seconds = secs % 60UL; 58 | secs /= 60UL; 59 | minutes = secs % 60UL; 60 | hours = secs / 60UL; 61 | 62 | snprintf ( clock, 63 | sizeof clock, 64 | "%02d:%02d:%02d", 65 | hours, // hour 66 | minutes, // minute 67 | seconds ); // second 68 | 69 | return clock; 70 | } 71 | -------------------------------------------------------------------------------- /src/timer.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef M_TIME_H 22 | #define M_TIME_H 23 | 24 | #include 25 | #include // struct timespec 26 | 27 | // return current time in milliseconds 28 | uint64_t 29 | get_time ( void ); 30 | 31 | // transform milliseconds in format hh:mm:ss 32 | char * 33 | msec2clock ( uint64_t milliseconds ); 34 | 35 | #endif // MTIME_H 36 | -------------------------------------------------------------------------------- /src/translate.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // snprintf 22 | #include 23 | #include 24 | #include // NI_MAXHOST, NI_MAXSERV 25 | #include // htons 26 | #include // IPPROTO_UDP | IPPROTO_TCP 27 | 28 | #include "translate.h" 29 | #include "sockaddr.h" 30 | #include "resolver/sock_util.h" 31 | #include "resolver/resolver.h" 32 | 33 | #define LEN_TUPLE ( ( NI_MAXHOST + NI_MAXSERV ) * 2 ) + 7 + 10 34 | 35 | char * 36 | translate ( const connection_t *con, const struct config_op *co ) 37 | { 38 | // NOTE: structs members should be zered 39 | 40 | // local_socket 41 | union sockaddr_all l_sock = { .in = { .sin_family = AF_INET, 42 | .sin_port = con->tuple.l4.local_port, 43 | .sin_addr.s_addr = 44 | con->tuple.l3.local.ip } }; 45 | 46 | // remote_socket 47 | union sockaddr_all r_sock = { .in = { .sin_family = AF_INET, 48 | .sin_port = con->tuple.l4.remote_port, 49 | .sin_addr.s_addr = 50 | con->tuple.l3.remote.ip } }; 51 | 52 | char l_host[NI_MAXHOST], r_host[NI_MAXHOST]; 53 | 54 | if ( co->translate_host ) 55 | { 56 | ip2domain ( &l_sock, l_host, sizeof ( l_host ) ); 57 | ip2domain ( &r_sock, r_host, sizeof ( r_host ) ); 58 | } 59 | else 60 | { 61 | sockaddr_ntop ( &l_sock, l_host, sizeof ( l_host ) ); 62 | sockaddr_ntop ( &r_sock, r_host, sizeof ( r_host ) ); 63 | } 64 | 65 | char l_service[NI_MAXSERV], r_service[NI_MAXSERV]; 66 | 67 | if ( co->translate_service ) 68 | { 69 | const char *proto = 70 | ( con->tuple.l4.protocol == IPPROTO_UDP ) ? "udp" : "tcp"; 71 | 72 | if ( !port2serv ( l_sock.in.sin_port, 73 | proto, 74 | l_service, 75 | sizeof ( l_service ) ) ) 76 | snprintf ( l_service, 77 | sizeof ( l_service ), 78 | "%u", 79 | con->tuple.l4.local_port ); 80 | 81 | if ( !port2serv ( r_sock.in.sin_port, 82 | proto, 83 | r_service, 84 | sizeof ( r_service ) ) ) 85 | snprintf ( r_service, 86 | sizeof ( r_service ), 87 | "%u", 88 | con->tuple.l4.remote_port ); 89 | } 90 | else 91 | { 92 | snprintf ( l_service, 93 | sizeof ( l_service ), 94 | "%u", 95 | con->tuple.l4.local_port ); 96 | snprintf ( r_service, 97 | sizeof ( r_service ), 98 | "%u", 99 | con->tuple.l4.remote_port ); 100 | } 101 | 102 | // tuple ip:port <-> ip:port 103 | static char tuple[LEN_TUPLE]; 104 | 105 | snprintf ( tuple, 106 | sizeof ( tuple ), 107 | "%s:%s <-> %s:%s", 108 | l_host, 109 | l_service, 110 | r_host, 111 | r_service ); 112 | 113 | return tuple; 114 | } 115 | -------------------------------------------------------------------------------- /src/translate.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef TRANSLETE_H 22 | #define TRANSLETE_H 23 | 24 | #include "connection.h" 25 | #include "config.h" 26 | 27 | char * 28 | translate ( const connection_t *con, const struct config_op *co ); 29 | 30 | #endif // TRANSLETE_H 31 | -------------------------------------------------------------------------------- /src/tui.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef SHOW_H 22 | #define SHOW_H 23 | 24 | #include "processes.h" // type process_t, MAX_NAME 25 | #include "config.h" 26 | 27 | // return of tui_handle_input 28 | #define P_EXIT 1 29 | #define P_CONTINE 0 30 | 31 | int 32 | tui_init ( const struct config_op *co ); 33 | 34 | void 35 | tui_show ( const struct processes *processes, const struct config_op *co ); 36 | 37 | // handle input of user while program is running 38 | int 39 | tui_handle_input ( const struct config_op *co ); 40 | 41 | void 42 | tui_free ( void ); 43 | 44 | #endif // SHOW_H 45 | -------------------------------------------------------------------------------- /src/usage.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include "config.h" 23 | 24 | void 25 | show_version ( void ) 26 | { 27 | puts ( PROG_NAME " - " PROG_VERSION ); 28 | } 29 | 30 | void 31 | usage ( void ) 32 | { 33 | show_version (); 34 | // clang-format off 35 | fputs ( "Usage: " PROG_NAME " [options]\n" 36 | "\n" 37 | "Options:\n" 38 | " -B, --bytes view in bytes, default in bits\n" 39 | " -c visualization each active connection of the process\n" 40 | " --color 1|2|3 color scheme, 1 is default\n" 41 | " -f, --file \"filename\" save statistics in file, filename is optional,\n" 42 | " default is '" PROG_NAME_LOG "'\n" 43 | " -h, --help show this message\n" 44 | " -i, --interface iface specifies an interface, default is all\n" 45 | " (except interface with network 127.0.0.0/8)\n" 46 | " -n numeric host and service, implicit '-c', try '-nh' to no\n" 47 | " translate only host or '-np' to not translate only service\n" 48 | " -p, --protocol tcp|udp specifies a protocol, the default is tcp and udp\n" 49 | " --si show SI format, with powers of 10, default is IEC,\n" 50 | " with powers of 2\n" 51 | " -v, --verbose verbose mode, also show process without traffic\n" 52 | " -V, --version show version\n" 53 | "\n" 54 | "when running press:\n" 55 | " arrow keys scroll\n" 56 | " s change column-based sort\n" 57 | " q exit\n" 58 | , stderr); 59 | // clang-format on 60 | } 61 | -------------------------------------------------------------------------------- /src/usage.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2020-2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef USAGE_H 22 | #define USAGE_H 23 | 24 | void 25 | usage ( void ); 26 | 27 | void 28 | show_version ( void ); 29 | 30 | #endif // USAGE_H 31 | -------------------------------------------------------------------------------- /src/vector.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include // realloc, free 22 | #include // memcpy 23 | 24 | struct vector 25 | { 26 | size_t elements_allocated; 27 | size_t elements_used; 28 | size_t element_size; 29 | }; 30 | 31 | /* CHUNK is header, MEM is user memory */ 32 | 33 | #define CHUNCK_TO_MEM( pos ) ( ( char * ) ( pos ) + sizeof ( struct vector ) ) 34 | #define MEM_TO_CHUNK( pos ) \ 35 | ( ( struct vector * ) ( ( char * ) ( pos ) - sizeof ( struct vector ) ) ) 36 | 37 | static void * 38 | vector_alloc ( struct vector *v, size_t size ) 39 | { 40 | return realloc ( v, size + sizeof ( struct vector ) ); 41 | } 42 | 43 | static void 44 | vector_copy ( struct vector *restrict v, void *restrict data ) 45 | { 46 | char *ptr = CHUNCK_TO_MEM ( v ) + ( v->elements_used * v->element_size ); 47 | 48 | memcpy ( ptr, data, v->element_size ); 49 | } 50 | 51 | #define LEN_INIT_VECTOR 16 52 | 53 | void * 54 | vector_new ( size_t size_member ) 55 | { 56 | struct vector *vt = vector_alloc ( NULL, LEN_INIT_VECTOR * size_member ); 57 | 58 | if ( vt ) 59 | { 60 | vt->elements_allocated = LEN_INIT_VECTOR; 61 | vt->elements_used = 0; 62 | vt->element_size = size_member; 63 | 64 | return CHUNCK_TO_MEM ( vt ); 65 | } 66 | 67 | return vt; 68 | } 69 | 70 | int 71 | vector_push_ ( void **restrict mem, void *restrict data ) 72 | { 73 | struct vector *vt = MEM_TO_CHUNK ( *mem ); 74 | 75 | if ( vt->elements_used == vt->elements_allocated ) 76 | { 77 | vt->elements_allocated <<= 1; 78 | size_t new_size = vt->elements_allocated * vt->element_size; 79 | void *temp = vector_alloc ( vt, new_size ); 80 | 81 | if ( !temp ) 82 | { 83 | vt->elements_allocated >>= 1; 84 | return 0; 85 | } 86 | 87 | if ( vt != temp ) 88 | { 89 | vt = temp; 90 | *mem = CHUNCK_TO_MEM ( vt ); 91 | } 92 | } 93 | 94 | vector_copy ( vt, data ); 95 | 96 | vt->elements_used++; 97 | 98 | return 1; 99 | } 100 | 101 | void * 102 | vector_pop ( void *mem ) 103 | { 104 | struct vector *vt = MEM_TO_CHUNK ( mem ); 105 | 106 | vt->elements_used--; 107 | 108 | return ( void * ) ( ( char * ) mem + vt->elements_used * vt->element_size ); 109 | } 110 | 111 | void 112 | vector_clear ( void *mem ) 113 | { 114 | struct vector *vt = MEM_TO_CHUNK ( mem ); 115 | 116 | vt->elements_used = 0; 117 | } 118 | 119 | size_t 120 | vector_size ( void *mem ) 121 | { 122 | struct vector *vt = MEM_TO_CHUNK ( mem ); 123 | 124 | return vt->elements_used; 125 | } 126 | 127 | void 128 | vector_free ( void *mem ) 129 | { 130 | free ( MEM_TO_CHUNK ( mem ) ); 131 | } 132 | -------------------------------------------------------------------------------- /src/vector.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2021 Mayco S. Berghetti 4 | * 5 | * This file is part of Netproc. 6 | * 7 | * Netproc is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef VECTOR_H 22 | #define VECTOR_H 23 | 24 | #include 25 | 26 | /* 27 | create new vector 28 | @param nmeb, number of member initial in vector, if 0 default is 16 29 | @param size, size of one member in array 30 | 31 | @return memory to user or null on error 32 | */ 33 | void * 34 | vector_new ( size_t size_member ); 35 | 36 | /* 37 | copy user data into vector 38 | @oaram mem, pointer returned from vector_new 39 | @param data, pointer to user data to push in vector 40 | 41 | @return 1 if success or 0 on error 42 | */ 43 | int 44 | vector_push_ ( void **mem, void *data ); 45 | 46 | #define vector_push( mem, data ) vector_push_ ( ( void ** ) ( &mem ), ( data ) ) 47 | 48 | /* 49 | remove last element from vector 50 | @oaram mem, pointer returned from vector_new 51 | 52 | @return element removed from vector 53 | */ 54 | void * 55 | vector_pop ( void *mem ); 56 | 57 | /* 58 | remove all vector elements 59 | @oaram mem, pointer returned from vector_new 60 | */ 61 | void 62 | vector_clear ( void *mem ); 63 | 64 | /* 65 | return number of elements in vector 66 | @oaram mem, pointer returned from vector_new 67 | */ 68 | size_t 69 | vector_size ( void *mem ); 70 | 71 | /* 72 | free vector 73 | @oaram mem, pointer returned from vector_new 74 | */ 75 | void 76 | vector_free ( void *mem ); 77 | 78 | #endif // VECTOR_H 79 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | 3 | !*.* 4 | 5 | !Makefile 6 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # specific unity, only append this variables 3 | C_SOURCE= ./unity/unity.c 4 | INC_DIRS= -Iunity 5 | 6 | CFLAGS=-Wall -Wextra -pedantic -ggdb -O0 -fsanitize=address 7 | LDFLAGS+= -fsanitize=address 8 | 9 | INC_DIRS += -I../src -I ../src/resolver 10 | 11 | C_TMP= $(wildcard ./test*.c) 12 | OBJS_TEST= $(C_TMP:.c=.o) 13 | 14 | TEST = tests_all 15 | 16 | # include here source module to test 17 | C_SOURCE += ../src/hashtable.c \ 18 | ../src/full_read.c \ 19 | ../src/resolver/queue.c \ 20 | ../src/str.c \ 21 | ../src/rate.c \ 22 | ../src/round.c \ 23 | ../src/human_readable.c \ 24 | ../src/vector.c \ 25 | ../src/timer.c \ 26 | ../src/m_error.c 27 | 28 | OBJS_MODS = $(C_SOURCE:.c=.o) 29 | 30 | .PHONY: all clean run 31 | 32 | all: $(TEST) run clean 33 | 34 | $(TEST): $(OBJS_TEST) $(OBJS_MODS) 35 | $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ 36 | 37 | %.o : %.c 38 | $(CC) $(CFLAGS) $(INC_DIRS) $(CPPFLAGS) -c $< -o $@ 39 | 40 | run: 41 | - ./$(TEST) 42 | 43 | clean: 44 | @ find . -type f -name '*.o' -delete 45 | # @ find . -executable -type f -delete 46 | -------------------------------------------------------------------------------- /tests/cycle_counting.h: -------------------------------------------------------------------------------- 1 | #ifndef CYCLE_COUNTING_INCLUDED__ 2 | #define CYCLE_COUNTING_INCLUDED__ 3 | 4 | #ifndef __GNUC__ 5 | #error Works only on GCC 6 | #endif 7 | 8 | #pragma GCC diagnostic ignored "-Wignored-qualifiers" 9 | 10 | // https://bitismyth.wordpress.com/2019/09/24/contador-do-homem-pobre-agora-com-suporta-ao-arm/ 11 | 12 | /* ========================================== 13 | Quick & Dirty cycle counting... 14 | 15 | As funções usadas para contar a quantidade de ciclos 16 | de clock gastos num bloco de código. 17 | 18 | Exemplo de uso: 19 | 20 | counter_T cnt; 21 | 22 | cnt = BEGIN_TSC(); 23 | f(); 24 | cnt = END_TSC(cnt); 25 | 26 | Defina SYNC_MEM se quiser uma serialização mais completa (mfence). 27 | ========================================== */ 28 | #include 29 | 30 | // É necessário usar esse "tipo" para os contadores 31 | // porque o compilador vai tentar otimizar qualquer variável 32 | // não volátil. 33 | typedef volatile uint64_t counter_T; 34 | 35 | #if defined( __x86_64__ ) 36 | static inline counter_T 37 | BEGIN_TSC ( void ) 38 | { 39 | uint32_t a, d; 40 | 41 | __asm__ __volatile__( 42 | #ifdef SYNC_MEM 43 | "mfence\n\t" 44 | #endif 45 | // "xorl %%eax,%%eax\n\t" 46 | "cpuid\n\t" 47 | "rdtsc" 48 | : "=a"( a ), "=d"( d ) 49 | : "a"( 0 ) 50 | : "rbx" ); 51 | 52 | return a | ( ( uint64_t ) d << 32 ); 53 | } 54 | 55 | static inline counter_T 56 | END_TSC ( const counter_T cptr ) 57 | { 58 | uint32_t a, d; 59 | 60 | __asm__ __volatile__( "rdtsc" : "=a"( a ), "=d"( d ) ); 61 | 62 | return ( a | ( ( uint64_t ) d << 32 ) ) - cptr; 63 | } 64 | 65 | #elif defined( __i386__ ) 66 | static inline counter_T 67 | BEGIN_TSC ( void ) 68 | { 69 | uint32_t a, d; 70 | 71 | __asm__ __volatile__( 72 | // Só usa mfence se o processador suportar SSE2. 73 | #ifdef __SSE2__ 74 | #ifdef SYNC_MEM 75 | "mfence\n\t" 76 | #endif 77 | #endif 78 | "xorl %%eax,%%eax\n\t" 79 | "cpuid\n\t" 80 | "rdtsc" 81 | : "=a"( a ), "=d"( d )::"%ebx", "%ecx" ); 82 | 83 | return a | ( ( uint64_t ) d << 32 ); 84 | } 85 | 86 | static inline void 87 | END_TSC ( counter_T *cptr ) 88 | { 89 | uint32_t a, d; 90 | 91 | __asm__ __volatile__( "rdtscp" : "=a"( a ), "=d"( d )::"%ecx" ); 92 | 93 | *cptr = ( a | ( ( uint64_t ) d << 32 ) ) - *cptr; 94 | } 95 | #elif __arm__ 96 | #if __ARM_32BIT_STATE == 1 97 | // This works only on ARMv8 98 | #if __ARM_ARCH__ > 7 99 | static inline counter_T 100 | BEGIN_TSC ( void ) 101 | { 102 | unsigned int r0, r1; 103 | 104 | __asm__ __volatile__( 105 | #ifdef SYNC_MEM 106 | "dmb\n\t" 107 | #endif 108 | "mrrc p15,1,%0,%1,c14" // FIXME: Must check this. 109 | // Get the virtual counter. 110 | : "=r"( r0 ), "=r"( r1 ) ); 111 | 112 | return ( ( uint64_t ) r1 << 32 ) | r0; 113 | } 114 | 115 | static inline void 116 | END_TSC ( counter_T *cptr ) 117 | { 118 | unsigned int r0, r1; 119 | 120 | __asm__ __volatile__( 121 | "mrrc p15,1,%0,%1,c14" // FIXME: Must check this. 122 | // get the virtual counter. 123 | : "=r"( r0 ), "=r"( r1 ) ); 124 | 125 | *cptr = ( ( ( uint64_t ) r1 << 32 ) | r0 ) - *cptr; 126 | } 127 | #else 128 | #error ARMv8 or superior only. 129 | #endif 130 | #else // otherwise we are in aarch64 mode. 131 | static inline counter_T 132 | BEGIN_TSC ( void ) 133 | { 134 | uint64_t count; 135 | 136 | __asm__ __volatile__( 137 | #ifdef SYNC_MEM 138 | "dmb\n\t" 139 | #endif 140 | "mrs %0,cntvct_el0" 141 | : "=r"( count ) ); 142 | 143 | return count; 144 | } 145 | 146 | static inline void 147 | END_TSC ( counter_T *cptr ) 148 | { 149 | uint64_t count; 150 | 151 | __asm__ __volatile__( "mrs %0,cntvct_el0" : "=r"( count ) ); 152 | 153 | *cptr = count - *cptr; 154 | } 155 | #endif 156 | #else 157 | #error i386, x86-64 and ARM only. 158 | #endif 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /tests/file_test_full_read.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berghetti/netproc/d6b22e19728dca1aab81442a89cf07b0574370cc/tests/file_test_full_read.bin -------------------------------------------------------------------------------- /tests/test_full_read.c: -------------------------------------------------------------------------------- 1 | 2 | #include // free 3 | #include // open 4 | #include 5 | #include 6 | #include // close 7 | 8 | #include "unity.h" 9 | #include "full_read.h" 10 | 11 | void 12 | test_full_read ( void ) 13 | { 14 | // echo -e -n '\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90' > 15 | // file_test_full_read.bin 16 | int fd = open ( "file_test_full_read.bin", O_RDONLY ); 17 | TEST_ASSERT ( fd != -1 ); 18 | 19 | char *buff; 20 | ssize_t total_read = full_read ( fd, &buff ); 21 | TEST_ASSERT ( total_read != -1 ); 22 | close ( fd ); 23 | 24 | TEST_ASSERT_NOT_NULL ( buff ); 25 | TEST_ASSERT_EQUAL_INT ( 10, total_read ); 26 | 27 | unsigned char expected[10] = { 0x00, 0x10, 0x20, 0x30, 0x40, 28 | 0x50, 0x60, 0x70, 0x80, 0x90 }; 29 | 30 | TEST_ASSERT_EQUAL_MEMORY ( expected, buff, 10 ); 31 | 32 | free ( buff ); 33 | } 34 | -------------------------------------------------------------------------------- /tests/test_hashtable.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "hashtable.h" 5 | #include "unity.h" 6 | #include "../src/macro_util.h" 7 | 8 | static int 9 | cb_func ( hashtable_t *ht, void *value, void *user_data ) 10 | { 11 | // ugly 12 | ht = ht; 13 | value = value; 14 | 15 | ( *( int * ) user_data )++; 16 | 17 | return 0; 18 | } 19 | 20 | #define FROM_PTR( p ) ( ( uintptr_t ) p ) 21 | #define TO_PTR( v ) ( ( void * ) ( uintptr_t ) v ) 22 | 23 | static bool 24 | cb_compare ( const void *key1, const void *key2 ) 25 | { 26 | return ( key1 == key2 ); 27 | } 28 | 29 | static hash_t 30 | cb_hash ( const void *key ) 31 | { 32 | int n = ( int ) FROM_PTR ( key ); 33 | 34 | return n; 35 | } 36 | 37 | void 38 | test1 ( void ) 39 | { 40 | hashtable_t *ht = hashtable_new ( cb_hash, cb_compare, NULL ); 41 | 42 | TEST_ASSERT_NOT_NULL ( ht ); 43 | TEST_ASSERT_EQUAL_INT ( 0, hashtable_get_nentries ( ht ) ); 44 | TEST_ASSERT_GREATER_THAN ( 0, hashtable_get_size ( ht ) ); 45 | 46 | TEST_ASSERT_NULL ( hashtable_get ( ht, 0 ) ); 47 | 48 | int values[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 0 }; 49 | int *p; 50 | 51 | size_t i; 52 | for ( i = 0; i < ARRAY_SIZE ( values ); i++ ) 53 | { 54 | p = hashtable_set ( ht, TO_PTR ( values[i] ), &values[i] ); 55 | TEST_ASSERT_EQUAL_INT ( values[i], *p ); 56 | } 57 | 58 | TEST_ASSERT_EQUAL_INT ( ARRAY_SIZE ( values ), 59 | hashtable_get_nentries ( ht ) ); 60 | TEST_ASSERT_GREATER_THAN ( hashtable_get_nentries ( ht ), 61 | hashtable_get_size ( ht ) ); 62 | 63 | for ( i = 0; i < ARRAY_SIZE ( values ); i++ ) 64 | { 65 | p = hashtable_get ( ht, TO_PTR ( values[i] ) ); 66 | TEST_ASSERT_EQUAL_INT ( *p, values[i] ); 67 | } 68 | 69 | p = hashtable_remove ( ht, TO_PTR ( values[0] ) ); 70 | TEST_ASSERT_EQUAL_INT ( *p, values[0] ); 71 | TEST_ASSERT_EQUAL_INT ( ARRAY_SIZE ( values ) - 1, 72 | hashtable_get_nentries ( ht ) ); 73 | TEST_ASSERT_NULL ( hashtable_remove ( ht, TO_PTR ( values[0] ) ) ); 74 | 75 | int count = 0; 76 | TEST_ASSERT_EQUAL_INT ( 0, hashtable_foreach ( ht, cb_func, &count ) ); 77 | TEST_ASSERT_EQUAL_INT ( ARRAY_SIZE ( values ) - 1, count ); 78 | TEST_ASSERT_EQUAL_INT ( count, hashtable_get_nentries ( ht ) ); 79 | 80 | hashtable_destroy ( ht ); 81 | } 82 | 83 | static bool 84 | cb_compare2 ( const void *key1, const void *key2 ) 85 | { 86 | return ( *( int * ) key1 == *( int * ) key2 ); 87 | } 88 | 89 | static hash_t 90 | cb_hash2 ( const void *key ) 91 | { 92 | return *( int * ) key; 93 | } 94 | 95 | static int 96 | remove_foreach ( UNUSED hashtable_t *ht, 97 | UNUSED void *value, 98 | UNUSED void *user_data ) 99 | { 100 | return 1; 101 | } 102 | 103 | static void 104 | test_hashtable_foreach_safe ( void ) 105 | { 106 | hashtable_t *ht = hashtable_new ( cb_hash2, cb_compare2, NULL ); 107 | 108 | int values[] = { 10, 20, 30, 40, 50, 60, 70, 80, 109 | 90, 100, 110, 120, 130, 140, 150 }; 110 | int *p; 111 | 112 | size_t i; 113 | for ( i = 0; i < ARRAY_SIZE ( values ); i++ ) 114 | { 115 | p = hashtable_set ( ht, &values[i], &values[i] ); 116 | TEST_ASSERT_EQUAL_INT ( values[i], *p ); 117 | } 118 | 119 | hashtable_foreach_remove ( ht, remove_foreach, NULL ); 120 | 121 | TEST_ASSERT_EQUAL_INT ( 0, hashtable_get_nentries ( ht ) ); 122 | 123 | hashtable_destroy ( ht ); 124 | } 125 | 126 | void 127 | test_hashtable ( void ) 128 | { 129 | test1 (); 130 | test_hashtable_foreach_safe (); 131 | } 132 | -------------------------------------------------------------------------------- /tests/test_ht_conn.c: -------------------------------------------------------------------------------- 1 | 2 | #include "unity/unity.h" 3 | 4 | #include "../src/connection.c" 5 | 6 | // #include "../src/m_error.h" 7 | // 8 | #include 9 | #include 10 | 11 | static connection_t * 12 | create_conn_fake ( void ) 13 | { 14 | connection_t *conn = calloc ( 1, sizeof *conn ); 15 | 16 | if ( conn ) 17 | { 18 | conn->inode = rand (); 19 | conn->tuple.l3.local.ip = rand (); 20 | conn->tuple.l3.remote.ip = rand (); 21 | conn->tuple.l4.local_port = rand () % 0xffff; 22 | conn->tuple.l4.remote_port = rand () % 0xffff; 23 | conn->refs_active = 3; 24 | } 25 | 26 | return conn; 27 | } 28 | 29 | #define NUM_CONN 16 30 | 31 | static void 32 | test_insert ( void ) 33 | { 34 | for ( int i = 0; i < NUM_CONN; i++ ) 35 | { 36 | connection_t *conn = create_conn_fake (); 37 | TEST_ASSERT_NOT_NULL ( conn ); 38 | 39 | connection_insert ( conn ); 40 | TEST_ASSERT_EQUAL_INT ( 2 * ( i + 1 ), 41 | hashtable_get_nentries ( ht_connections ) ); 42 | } 43 | } 44 | 45 | static void 46 | test_search ( void ) 47 | { 48 | connection_t *conn = create_conn_fake (); 49 | TEST_ASSERT_NOT_NULL ( conn ); 50 | 51 | TEST_ASSERT_NULL ( connection_get_by_inode ( conn->inode ) ); 52 | TEST_ASSERT_NULL ( connection_get_by_tuple ( &conn->tuple ) ); 53 | 54 | connection_insert ( conn ); 55 | 56 | TEST_ASSERT_EQUAL ( 2 * ( NUM_CONN + 1 ), 57 | hashtable_get_nentries ( ht_connections ) ); 58 | 59 | connection_t *tmp; 60 | 61 | tmp = connection_get_by_inode ( conn->inode ); 62 | TEST_ASSERT_EQUAL_PTR ( conn, tmp ); 63 | 64 | tmp = connection_get_by_tuple ( &conn->tuple ); 65 | TEST_ASSERT_EQUAL_PTR ( conn, tmp ); 66 | } 67 | 68 | static void 69 | test_delete ( void ) 70 | { 71 | hashtable_foreach_remove ( ht_connections, remove_inactives_conns, NULL ); 72 | TEST_ASSERT_EQUAL ( NUM_CONN * 2 + 2, 73 | hashtable_get_nentries ( ht_connections ) ); 74 | 75 | // removed conns only next update 76 | hashtable_foreach_remove ( ht_connections, remove_inactives_conns, NULL ); 77 | TEST_ASSERT_EQUAL ( 0, hashtable_get_nentries ( ht_connections ) ); 78 | } 79 | 80 | static void 81 | test_conn_update ( void ) 82 | { 83 | TEST_ASSERT_TRUE ( connection_update ( TCP | UDP ) ); 84 | } 85 | 86 | void 87 | test_ht_conn ( void ) 88 | { 89 | srand ( time ( NULL ) ); 90 | 91 | TEST_ASSERT_TRUE ( connection_init () ); 92 | 93 | test_insert (); 94 | test_search (); 95 | test_delete (); 96 | 97 | test_conn_update (); 98 | size_t hold = hashtable_get_nentries ( ht_connections ); 99 | hashtable_foreach_remove ( ht_connections, remove_inactives_conns, NULL ); 100 | TEST_ASSERT_EQUAL ( hold, hashtable_get_nentries ( ht_connections ) ); 101 | 102 | hashtable_foreach_remove ( ht_connections, remove_inactives_conns, NULL ); 103 | TEST_ASSERT_EQUAL ( 0, hashtable_get_nentries ( ht_connections ) ); 104 | 105 | connection_free (); 106 | } 107 | -------------------------------------------------------------------------------- /tests/test_human_readable.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "unity.h" 7 | #include "config.h" 8 | #include "human_readable.h" 9 | 10 | #pragma GCC diagnostic ignored "-Wunused-value" 11 | 12 | // #define DPRINT 1 13 | 14 | #ifdef DPRINT 15 | #define PRINT printf 16 | #else 17 | #define PRINT 18 | #endif 19 | 20 | #define ARRAY_SIZE( ar ) ( sizeof ( ar ) / sizeof ( ar[0] ) ) 21 | 22 | static char buff[14]; 23 | 24 | void 25 | test_Byte_per_second_si ( void ) 26 | { 27 | int values[] = { 0, 500, 1024, 2048, 5000, 9999, 10485760 }; 28 | char *expected[] = { "0", "500 B/s", "1.00 KiB/s", "2.00 KiB/s", 29 | "4.88 KiB/s", "9.76 KiB/s", "10.00 MiB/s" }; 30 | 31 | define_sufix ( false, true ); 32 | 33 | for ( size_t i = 0; i < ARRAY_SIZE ( values ); i++ ) 34 | { 35 | TEST_ASSERT_TRUE ( 36 | human_readable ( buff, sizeof ( buff ), values[i], RATE ) ); 37 | PRINT ( "%s\n", buff ); 38 | TEST_ASSERT_EQUAL_STRING ( expected[i], buff ); 39 | } 40 | } 41 | 42 | void 43 | test_bit_per_second_si ( void ) 44 | { 45 | int values[] = { 0, 1015, 1024, 2048, 6000, 9999, 10485760 }; 46 | char *expected[] = { "0", "1015 b/s", "1.00 Kib/s", "2.00 Kib/s", 47 | "5.86 Kib/s", "9.76 Kib/s", "10.00 Mib/s" }; 48 | 49 | define_sufix ( false, false ); 50 | 51 | for ( size_t i = 0; i < ARRAY_SIZE ( values ); i++ ) 52 | { 53 | TEST_ASSERT_TRUE ( 54 | human_readable ( buff, sizeof ( buff ), values[i], RATE ) ); 55 | PRINT ( "%s\n", buff ); 56 | TEST_ASSERT_EQUAL_STRING ( expected[i], buff ); 57 | } 58 | } 59 | 60 | void 61 | test_bit_per_second_iec ( void ) 62 | { 63 | int values[] = { 0, 999, 1015, 1024, 6000, 9999, 10485760 }; 64 | char *expected[] = { "0", "999 b/s", "1.01 Kb/s", "1.02 Kb/s", 65 | "6.00 Kb/s", "10.00 Kb/s", "10.48 Mb/s" }; 66 | 67 | define_sufix ( true, false ); 68 | 69 | for ( size_t i = 0; i < ARRAY_SIZE ( values ); i++ ) 70 | { 71 | TEST_ASSERT_TRUE ( 72 | human_readable ( buff, sizeof ( buff ), values[i], RATE ) ); 73 | PRINT ( "%s\n", buff ); 74 | TEST_ASSERT_EQUAL_STRING ( expected[i], buff ); 75 | } 76 | } 77 | 78 | void 79 | test_human_readable ( void ) 80 | { 81 | test_Byte_per_second_si (); 82 | 83 | test_bit_per_second_si (); 84 | 85 | test_bit_per_second_iec (); 86 | } 87 | -------------------------------------------------------------------------------- /tests/test_packet.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include // sleep 4 | 5 | #include "unity.h" 6 | #include "../src/packet.c" 7 | 8 | static void 9 | test_dont_fragment ( void ) 10 | { 11 | struct iphdr ip = { .frag_off = htons ( IP_DF ) }; 12 | 13 | TEST_ASSERT_EQUAL_INT ( -1, get_fragment ( &ip, NULL ) ); 14 | } 15 | 16 | struct pkt 17 | { 18 | struct iphdr l3; 19 | struct layer_4 l4; 20 | }; 21 | 22 | static void 23 | test_more_fragment ( void ) 24 | { 25 | int ret; 26 | 27 | struct pkt pkt_1 = { .l3 = { .frag_off = htons ( IP_MF ), 28 | .id = 1, 29 | .saddr = 0x01010101, 30 | .daddr = 0x02020202 }, 31 | .l4 = { .source = 1025, .dest = 80 } }; 32 | 33 | ret = get_fragment ( &pkt_1.l3, &pkt_1.l4 ); // should be first frag 34 | TEST_ASSERT_EQUAL_INT ( 0, ret ); // first position array pkt_ip_frag 35 | 36 | // test else if in get_fragment 37 | pkt_1.l3.frag_off |= 1; 38 | ret = get_fragment ( 39 | &pkt_1.l3, 40 | &pkt_1.l4 ); // now shold be different -1 because is one fragment 41 | TEST_ASSERT_EQUAL_INT ( 0, ret ); // first position of array pkt_ip_frag 42 | 43 | TEST_ASSERT_EQUAL_INT ( pkt_1.l4.source, pkt_ip_frag[ret].source_port ); 44 | TEST_ASSERT_EQUAL_INT ( pkt_1.l4.dest, pkt_ip_frag[ret].dest_port ); 45 | TEST_ASSERT_EQUAL_INT ( pkt_1.l3.id, pkt_ip_frag[ret].id ); 46 | 47 | struct pkt pkt_2 = { 48 | .l3 = { .frag_off = htons ( IP_MF ), 49 | .id = 1, // same id pkt_1, but address differents 50 | .saddr = 0x05050505, 51 | .daddr = 0x06060606 }, 52 | .l4 = { .source = 1030, .dest = 443 } 53 | }; 54 | 55 | ret = get_fragment ( &pkt_2.l3, &pkt_2.l4 ); 56 | TEST_ASSERT_EQUAL_INT ( 1, ret ); // second position of array pkt_ip_frag 57 | 58 | pkt_2.l3.frag_off |= 1; 59 | ret = get_fragment ( &pkt_2.l3, &pkt_1.l4 ); 60 | TEST_ASSERT_EQUAL_INT ( 1, ret ); 61 | 62 | TEST_ASSERT_EQUAL_INT ( pkt_2.l4.source, pkt_ip_frag[ret].source_port ); 63 | TEST_ASSERT_EQUAL_INT ( pkt_2.l4.dest, pkt_ip_frag[ret].dest_port ); 64 | TEST_ASSERT_EQUAL_INT ( pkt_2.l3.id, pkt_ip_frag[ret].id ); 65 | } 66 | 67 | static void 68 | test_clear_frag ( void ) 69 | { 70 | struct pkt pkt = { .l3 = { .frag_off = htons ( IP_MF ), 71 | .id = 3, 72 | .saddr = 0x01010101, 73 | .daddr = 0x02020202 }, 74 | .l4 = { .source = 1025, .dest = 80 } }; 75 | 76 | int ret = get_fragment ( &pkt.l3, &pkt.l4 ); 77 | TEST_ASSERT_NOT_EQUAL_INT ( -1, ret ); // should be a fragment 78 | 79 | // make a fragment 80 | pkt.l3.frag_off |= 1; 81 | pkt_ip_frag[ret].ttl -= LIFETIME_FRAG; 82 | clear_frag (); // should remove packet of array of fragments 83 | 84 | pkt.l3.frag_off = 0; 85 | TEST_ASSERT_EQUAL_INT ( -1, get_fragment ( &pkt.l3, &pkt.l4 ) ); 86 | } 87 | 88 | static void 89 | test_err_fragment ( void ) 90 | { 91 | struct pkt pkt = { .l3 = { .frag_off = htons ( IP_MF ), 92 | .id = 3, 93 | .saddr = 0x01010101, 94 | .daddr = 0x02020202 }, 95 | .l4 = { .source = 1025, .dest = 80 } }; 96 | 97 | pkt.l3.frag_off |= 1; // make this a fragment whith offset diferente de 0 98 | 99 | // is a fragment, but as offset is not 0, not was stored in buffer 100 | TEST_ASSERT_EQUAL_INT ( ERR_FRAGMENT, get_fragment ( &pkt.l3, &pkt.l4 ) ); 101 | } 102 | 103 | void 104 | test_packet ( void ) 105 | { 106 | test_dont_fragment (); 107 | test_more_fragment (); 108 | test_clear_frag (); 109 | test_err_fragment (); 110 | } 111 | -------------------------------------------------------------------------------- /tests/test_queue.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "queue.h" 5 | #include "unity.h" 6 | 7 | #define TOT_DATA 99 8 | 9 | struct mydata 10 | { 11 | int data; 12 | }; 13 | 14 | static struct mydata * 15 | create_mydata ( size_t i ) 16 | { 17 | struct mydata *d = malloc ( sizeof *d ); 18 | TEST_ASSERT_NOT_NULL ( d ); 19 | 20 | d->data = i; 21 | return d; 22 | } 23 | 24 | void 25 | test_queue ( void ) 26 | { 27 | struct queue *q = queue_new ( free ); 28 | TEST_ASSERT_NOT_NULL ( q ); 29 | 30 | // enqueue return size of queue if sucess, this should be different of 0 31 | for ( int i = 0; i < TOT_DATA; i++ ) 32 | { 33 | TEST_ASSERT_EQUAL_INT ( i + 1, enqueue ( q, create_mydata ( i ) ) ); 34 | } 35 | 36 | TEST_ASSERT_EQUAL_INT ( TOT_DATA, get_queue_size ( q ) ); 37 | 38 | struct mydata *d; 39 | for ( int i = 0; i < TOT_DATA - 5; i++ ) 40 | { 41 | TEST_ASSERT_NOT_NULL ( ( d = dequeue ( q ) ) ); 42 | TEST_ASSERT_EQUAL_INT ( i, d->data ); 43 | free ( d ); 44 | } 45 | 46 | TEST_ASSERT_EQUAL_INT ( 5, get_queue_size ( q ) ); 47 | 48 | queue_destroy ( q ); 49 | } 50 | -------------------------------------------------------------------------------- /tests/test_rate.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "unity.h" 5 | #include "processes.h" 6 | #include "config.h" 7 | 8 | #include "rate.h" 9 | 10 | void 11 | exec ( struct processes *processes ) 12 | { 13 | process_t *proc = *( processes->proc ); 14 | 15 | struct config_op co = { .view_bytes = 1 }; 16 | 17 | uint64_t expected_rx = 0, expected_tx = 0; 18 | 19 | // simulate 5 seconds of test 20 | int times = 5; 21 | while ( times-- ) 22 | { 23 | for ( int i = 0; i < SAMPLE_SPACE_SIZE; i++ ) 24 | { 25 | // first time is needed increase of value expected 26 | if ( times == 4 ) 27 | { 28 | expected_rx += 1000; // exact value to avoid rounding 29 | expected_tx += 500; 30 | } 31 | 32 | // max value after first time must be always 5000 / SAMPLE_SPACE_SIZE 33 | rate_add_rx ( &proc->net_stat, 1000 ); 34 | rate_add_tx ( &proc->net_stat, 500 ); 35 | 36 | rate_calc ( processes, &co ); 37 | 38 | TEST_ASSERT_EQUAL_INT ( expected_rx / SAMPLE_SPACE_SIZE, 39 | proc->net_stat.avg_Bps_rx ); 40 | TEST_ASSERT_EQUAL_INT ( expected_tx / SAMPLE_SPACE_SIZE, 41 | proc->net_stat.avg_Bps_tx ); 42 | 43 | // rotate e clean slot 44 | rate_update ( processes, &co ); 45 | } 46 | } 47 | } 48 | 49 | void 50 | test_rate ( void ) 51 | { 52 | process_t *proc = calloc ( 1, sizeof *proc ); 53 | process_t *pp_procs[] = { proc, NULL }; 54 | struct processes processes = { .proc = pp_procs, .total = 1 }; 55 | 56 | exec ( &processes ); 57 | 58 | free ( proc ); 59 | } 60 | -------------------------------------------------------------------------------- /tests/test_sec2clock.c: -------------------------------------------------------------------------------- 1 | 2 | #include "timer.h" 3 | #include "unity.h" 4 | 5 | #include "cycle_counting.h" 6 | 7 | struct test_set 8 | { 9 | uint64_t ml; 10 | char *expected; 11 | }; 12 | 13 | static struct test_set test[] = { 14 | { 0, "00:00:00" }, { 1000, "00:00:01" }, 15 | { 53646154, "14:54:06" }, { 172800000, "48:00:00" }, 16 | { 172810000, "48:00:10" }, { 1800752000, "500:12:32" } 17 | }; 18 | 19 | void 20 | test_performance ( void ) 21 | { 22 | counter_T cnt; 23 | 24 | cnt = BEGIN_TSC (); 25 | char *p = msec2clock ( 1800752000 ); 26 | cnt = END_TSC ( cnt ); 27 | 28 | printf ( "%s\ncycles = %lu\n", p, cnt ); 29 | } 30 | 31 | #define ARRAY_SIZE( x ) ( sizeof ( x ) / sizeof ( x[0] ) ) 32 | 33 | void 34 | test_sec2clock ( void ) 35 | { 36 | for ( uint32_t i = 0; i < ARRAY_SIZE ( test ); i++ ) 37 | { 38 | TEST_ASSERT_EQUAL_STRING ( test[i].expected, msec2clock ( test[i].ml ) ); 39 | } 40 | 41 | // test_performance(); 42 | } 43 | -------------------------------------------------------------------------------- /tests/test_str.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "str.h" 6 | #include "unity.h" 7 | 8 | void 9 | test_str () 10 | { 11 | // 300 'A' + 1 'space' + 2 'B'... 12 | const char *str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 13 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 14 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 15 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 16 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 17 | "AAAAAAAAAA BB CCC DDDD E"; 18 | 19 | TEST_ASSERT_EQUAL_INT ( 300, strlen_space ( str ) ); 20 | 21 | TEST_ASSERT_EQUAL_INT ( 302, index_last_char ( str, 'B' ) ); 22 | TEST_ASSERT_EQUAL_INT ( 306, index_last_char ( str, 'C' ) ); 23 | 24 | TEST_ASSERT_EQUAL_INT ( 'E', str[index_last_char ( str, 'E' )] ); 25 | 26 | TEST_ASSERT_EQUAL_INT ( -1, index_last_char ( str, 'G' ) ); 27 | 28 | const char *str2 = "/usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 123:134"; 29 | TEST_ASSERT_EQUAL_INT ( 14, strlen_space ( str2 ) ); 30 | } 31 | -------------------------------------------------------------------------------- /tests/test_vector.c: -------------------------------------------------------------------------------- 1 | 2 | // #include 3 | #include 4 | #include 5 | 6 | #include "unity.h" 7 | #include "vector.h" 8 | 9 | void 10 | test_vector_int ( void ) 11 | { 12 | #define COUNT 0xF 13 | 14 | int *vi = vector_new ( sizeof ( int ) ); 15 | 16 | TEST_ASSERT_TRUE ( vi ); 17 | 18 | for ( size_t i = 0; i < COUNT; ++i ) 19 | { 20 | TEST_ASSERT_TRUE ( vector_push ( vi, &i ) ); 21 | } 22 | 23 | TEST_ASSERT_EQUAL_INT ( COUNT, vector_size ( vi ) ); 24 | 25 | for ( size_t i = 0; i < COUNT; i++ ) 26 | { 27 | int *d = vector_pop ( vi ); 28 | TEST_ASSERT_EQUAL_INT ( COUNT - i - 1, *d ); 29 | TEST_ASSERT_EQUAL_INT ( i, vi[i] ); 30 | } 31 | 32 | vector_free ( vi ); 33 | } 34 | 35 | struct mydata 36 | { 37 | int a; 38 | int b; 39 | }; 40 | 41 | void 42 | test_vector_my_data ( void ) 43 | { 44 | struct mydata data1 = { .a = 1, .b = 2 }, data2 = { .a = 5, .b = 10 }; 45 | 46 | struct mydata *vt_data = vector_new ( sizeof *vt_data ); 47 | 48 | TEST_ASSERT_TRUE ( vt_data ); 49 | 50 | TEST_ASSERT_TRUE ( vector_push ( vt_data, &data1 ) ); 51 | TEST_ASSERT_TRUE ( vector_push ( vt_data, &data2 ) ); 52 | 53 | TEST_ASSERT_EQUAL_INT ( 2, vector_size ( vt_data ) ); 54 | 55 | TEST_ASSERT_EQUAL_INT ( 1, vt_data[0].a ); 56 | TEST_ASSERT_EQUAL_INT ( 2, vt_data[0].b ); 57 | TEST_ASSERT_EQUAL_INT ( 5, vt_data[1].a ); 58 | TEST_ASSERT_EQUAL_INT ( 10, vt_data[1].b ); 59 | 60 | struct mydata *res = vector_pop ( vt_data ); 61 | 62 | TEST_ASSERT_EQUAL_INT ( 5, res->a ); 63 | TEST_ASSERT_EQUAL_INT ( 10, res->b ); 64 | 65 | TEST_ASSERT_EQUAL_INT ( 1, vector_size ( vt_data ) ); 66 | 67 | // printf("%p\n%p\n", &data2, res ); 68 | // 69 | // printf("%d\n%d\n", res->b, res->a ); 70 | 71 | vector_free ( vt_data ); 72 | } 73 | 74 | void 75 | test_heap ( void ) 76 | { 77 | int **v = vector_new ( sizeof ( int * ) ); 78 | 79 | TEST_ASSERT_NOT_NULL ( v ); 80 | 81 | int size = 5; 82 | 83 | for ( int i = 0; i < size; i++ ) 84 | { 85 | int *d = malloc ( sizeof ( int ) ); 86 | *d = i; 87 | vector_push ( v, &d ); 88 | } 89 | 90 | for ( int i = 0; i < size; i++ ) 91 | { 92 | int **d = vector_pop ( v ); 93 | 94 | // printf("%d\n", **d); 95 | TEST_ASSERT_EQUAL_INT ( size - i - 1, **d ); 96 | free ( *d ); 97 | } 98 | 99 | vector_free ( v ); 100 | } 101 | 102 | void 103 | test_vector ( void ) 104 | { 105 | test_vector_int (); 106 | test_vector_my_data (); 107 | test_heap (); 108 | } 109 | -------------------------------------------------------------------------------- /tests/tests_all.c: -------------------------------------------------------------------------------- 1 | 2 | #include "unity.h" 3 | // clang-format off 4 | 5 | // include here test functions definition 6 | void test_hashtable ( void ); 7 | void test_full_read ( void ); 8 | void test_queue ( void ); 9 | void test_str ( void ); 10 | void test_rate ( void ); 11 | void test_human_readable ( void ); 12 | void test_packet ( void ); 13 | void test_vector ( void ); 14 | void test_sec2clock ( void ); 15 | void test_ht_conn( void ); 16 | 17 | // need to unity 18 | void setUp ( void ) { /* set stuff up here */ } 19 | void tearDown ( void ) { /* clean stuff up here */ } 20 | // clang-format on 21 | 22 | int 23 | main ( void ) 24 | { 25 | UNITY_BEGIN (); 26 | RUN_TEST ( test_hashtable ); 27 | RUN_TEST ( test_full_read ); 28 | RUN_TEST ( test_queue ); 29 | RUN_TEST ( test_str ); 30 | RUN_TEST ( test_rate ); 31 | RUN_TEST ( test_human_readable ); 32 | RUN_TEST ( test_packet ); 33 | RUN_TEST ( test_vector ); 34 | RUN_TEST ( test_sec2clock ); 35 | RUN_TEST ( test_ht_conn ); 36 | 37 | return UNITY_END (); 38 | } 39 | -------------------------------------------------------------------------------- /tests/tick_tack.c: -------------------------------------------------------------------------------- 1 | // gcc -o tick_tack tick_tack.c ../src/timer.c -Wall -Wextra && ./tick_tack 2 | 3 | // this is a stupid test done to check for a bug, 4 | // run this will stress the cpu 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../src/timer.h" 11 | 12 | // in milliseconds 13 | #define ONE_SEC 1000 14 | 15 | void 16 | tick_tack ( uint64_t running ) 17 | { 18 | static int tick_tack = 0; 19 | 20 | printf ( "%s - %s\n", 21 | ( tick_tack ) ? "tack" : "tick", 22 | msec2clock ( running ) ); 23 | 24 | tick_tack = !tick_tack; 25 | } 26 | 27 | int 28 | main ( void ) 29 | { 30 | uint64_t cur_time = get_time (); 31 | uint64_t running = 0; 32 | 33 | tick_tack ( running ); 34 | while ( 1 ) 35 | { 36 | uint64_t new_time = get_time (); 37 | 38 | if ( new_time < cur_time ) 39 | continue; 40 | 41 | uint32_t diff_time = new_time - cur_time; 42 | 43 | if ( diff_time >= ONE_SEC ) 44 | { 45 | running += diff_time; 46 | diff_time -= ONE_SEC; 47 | cur_time = new_time + diff_time; 48 | 49 | tick_tack ( running ); 50 | } 51 | } 52 | 53 | return 0; 54 | } 55 | --------------------------------------------------------------------------------