├── TODO.txt ├── .gitignore ├── ban2fail.service ├── cron-rpt.sh ├── add-addrs.sh ├── install.sh ├── cntry.h ├── maxoff.h ├── Jmakefile ├── iptables.h ├── ez_libanl.h ├── timestamp.h ├── target.h ├── cntry.c ├── addrRpt.h ├── ez_libanl.c ├── ban2fail.sh ├── fsckdns.c ├── pdns.h ├── obsvTpl.h ├── ez_libpthread.h ├── dynstack.h ├── ez_libz.h ├── ez_libdb.h ├── ez_libpthread.c ├── logType.h ├── offEntry.h ├── ban2fail.h ├── logFile.h ├── ban2fail.cfg ├── target.c ├── addrRpt.c ├── ez_libdb.c ├── msgqueue.c ├── ez.h ├── timestamp.c ├── dynstack.c ├── msgqueue.h ├── obsvTpl.c ├── maxoff.c ├── ez_libz.c ├── map.h ├── str.h ├── ptrvec.c ├── ptrvec.h ├── es.h ├── offEntry.c ├── Makefile ├── cfgmap.h └── logFile.c /TODO.txt: -------------------------------------------------------------------------------- 1 | * Parallelize log file scanning 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | debug 2 | release 3 | tags 4 | go.sh 5 | real-ban2fail.cfg 6 | -------------------------------------------------------------------------------- /ban2fail.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Log file scanning and iptables filtering 3 | ConditionPathExists=/usr/local/share/ban2fail/ban2fail.sh 4 | 5 | [Service] 6 | WorkingDirectory=/tmp 7 | Type=simple 8 | ExecStart=/usr/local/share/ban2fail/ban2fail.sh 9 | TimeoutSec=0 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /cron-rpt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | set -u 4 | 5 | BAN2FAIL=/usr/local/bin/ban2fail 6 | TMPFILE=/tmp/$$.cron-rpt.sh 7 | 8 | trap "[[ -e $TMPFILE ]] && rm $TMPFILE" 0 9 | 10 | $BAN2FAIL -a- >$TMPFILE 11 | 12 | while read; do 13 | MATCH=$(<$TMPFILE egrep "$REPLY\>") 14 | [[ "$MATCH" =~ BLK ]] || continue 15 | echo "$MATCH" 16 | done <<\_EOF_ 17 | google\.com 18 | outbound\.protection\.outlook\.com 19 | mail-mail\.facebook\.com 20 | yahoo\.com 21 | _EOF_ 22 | 23 | <$TMPFILE sed '0,/===============================================/ d' 24 | 25 | 26 | exit 0 27 | -------------------------------------------------------------------------------- /add-addrs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Add new addresses to ban2fail 4 | 5 | set -efu 6 | 7 | WD=~/projects/ban2fail 8 | PROTO_CFG=$WD/real-ban2fail.cfg 9 | ACTUAL_CFG=/etc/ban2fail/ban2fail.cfg 10 | BAN2FAIL=/usr/local/bin/ban2fail 11 | B2F_GREP=/usr/local/bin/b2f-grep 12 | MD5SUM= 13 | NEW_MD5SUM= 14 | JUNK= 15 | SEP= 16 | IP= 17 | PRTL_IP= 18 | LINE= 19 | 20 | trap "echo && $BAN2FAIL -s" 0 21 | 22 | while true; do 23 | 24 | read MD5SUM JUNK < <(md5sum $ACTUAL_CFG) 25 | 26 | read -p 'Next address(es) please? ' IP 27 | 28 | # Only consider editing PROTO_CFG is IP is not empty. 29 | if [[ -n "$IP" ]]; then 30 | 31 | $BAN2FAIL $IP 32 | 33 | echo '--------------------------------' 34 | 35 | read -p 'Edit config file? ' 36 | case ${REPLY:0:1} in 37 | y|Y) true;; 38 | *) continue;; 39 | esac 40 | 41 | # Edit all addresses we got from b2f-grep 42 | for LINE in $(2>/dev/null $B2F_GREP $IP <$PROTO_CFG); do 43 | $EDITOR +${LINE} $PROTO_CFG 44 | done 45 | fi 46 | 47 | # See if PROTO_CFG was changed. 48 | read NEW_MD5SUM JUNK < <(md5sum $PROTO_CFG) 49 | [[ $NEW_MD5SUM == $MD5SUM ]] && continue 50 | 51 | 52 | $BAN2FAIL -t $PROTO_CFG 53 | read -p 'Make this permanent? ' 54 | case ${REPLY:0:1} in 55 | y|Y) true;; 56 | *) continue;; 57 | esac 58 | sudo /bin/cp $PROTO_CFG $ACTUAL_CFG 59 | $BAN2FAIL -s 60 | done 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | set -u 4 | 5 | if [[ $(id -u) != 0 ]]; then 6 | echo 'This script must be run as root!' 7 | exit 1 8 | fi 9 | 10 | BINDIR=/usr/local/bin 11 | CONFDIR=/etc/ban2fail 12 | OTHERDIR=/usr/local/share/ban2fail 13 | SVCDIR=/etc/systemd/system 14 | 15 | BIN=ban2fail 16 | CONF=ban2fail.cfg 17 | SVC=ban2fail.service 18 | SVCSH=ban2fail.sh 19 | CACHEDIR=/var/cache/ban2fail 20 | TEST_CACHEDIR=${CACHEDIR}-test 21 | LOCKDIR=/run/lock/ban2fail 22 | TEST_LOCKDIR=${LOCKDIR}-test 23 | 24 | # Make sure directories exist with correct ownership & mode 25 | [[ -e $OTHERDIR ]] || mkdir $OTHERDIR 26 | chmod 2755 $OTHERDIR 27 | chown .adm $OTHERDIR 28 | 29 | [[ -e $CONFDIR ]] || mkdir $CONFDIR 30 | chmod 2750 $CONFDIR 31 | chown .adm $CONFDIR 32 | # TODO: substitute correct hostname in config 33 | [[ -e $CONFDIR/$CONF ]] || cp $CONF $CONFDIR 34 | 35 | [[ -e $BINDIR ]] || mkdir $BINDIR 36 | 37 | # No need for debugging symbols in binary 38 | strip release/$BIN 39 | cp -f release/$BIN $BINDIR/ 40 | chown .adm $BINDIR/$BIN 41 | # Need suid bit so non-root can run iptables 42 | chmod 4755 $BINDIR/$BIN 43 | 44 | chmod +x $SVCSH 45 | cp -f $SVCSH $OTHERDIR/ 46 | 47 | systemctl status ban2fail &>/dev/null && systemctl stop ban2fail 48 | # Clean out cache and lockfiles 49 | [[ -e $CACHEDIR ]] && rm -r $CACHEDIR 50 | [[ -e $TEST_CACHEDIR ]] && rm -r $TEST_CACHEDIR 51 | [[ -e $LOCKDIR ]] && rm -r $LOCKDIR 52 | [[ -e $TEST_LOCKDIR ]] && rm -r $TEST_LOCKDIR 53 | cp $SVC $SVCDIR/ 54 | systemctl daemon-reload 55 | systemctl start ban2fail 56 | systemctl enable ban2fail 57 | 58 | echo "Installation completed successfully" 59 | systemctl status ban2fail 60 | exit 0 61 | -------------------------------------------------------------------------------- /cntry.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef COUNTRY_H 20 | #define COUNTRY_H 21 | 22 | #include "cfgmap.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | const char* 29 | COUNTRY_get_code(const char *addr); 30 | /******************************************************** 31 | * Return a pointer to the 2 letter country abbrev, 32 | * or NULL if not known. 33 | */ 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif 38 | 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /maxoff.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | 20 | #ifndef MAXOFF_H 21 | #define MAXOFF_H 22 | 23 | #include "cfgmap.h" 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | int 30 | MAXOFF_allowed(const char *addr); 31 | /******************************************************** 32 | * Returns the maximum number of allowed offenses. 33 | * -1 means unlimited. 34 | */ 35 | 36 | int 37 | MAXOFF_init(CFGMAP *h_map, char *pfix); 38 | /************************************************************** 39 | * Initialize objects from configuration map. 40 | */ 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /Jmakefile: -------------------------------------------------------------------------------- 1 | baseDir := ~ 2 | libsDir := $(baseDir)/libs 3 | projectName := ban2fail 4 | versions := debug release 5 | cc_exe := ban2fail b2f-grep 6 | #install_dir := /usr/local/bin 7 | 8 | ######################################## 9 | # Set up sources & libraries here. # 10 | ######################################## 11 | 12 | ifeq ($(exe), ban2fail) 13 | src := \ 14 | addrRpt.c \ 15 | ban2fail.c \ 16 | cfgmap.c \ 17 | cntry.c \ 18 | dynstack.c \ 19 | es.c \ 20 | ez_libc.c \ 21 | ez_libdb.c \ 22 | ez_libpthread.c \ 23 | ez_libz.c \ 24 | iptables.c \ 25 | logType.c \ 26 | logFile.c \ 27 | map.c \ 28 | maxoff.c \ 29 | msgqueue.c \ 30 | obsvTpl.c \ 31 | offEntry.c \ 32 | pdns.c \ 33 | ptrvec.c \ 34 | str.c \ 35 | target.c \ 36 | timestamp.c \ 37 | util.c \ 38 | 39 | libs += z crypto GeoIP pthread db 40 | endif 41 | 42 | ifeq ($(exe), b2f-grep) 43 | src := \ 44 | ez_libc.c \ 45 | b2f-grep.c \ 46 | ptrvec.c \ 47 | str.c \ 48 | util.c \ 49 | 50 | libs += gmp 51 | endif 52 | 53 | 54 | ifeq ($(exe), fsckdns) 55 | src := \ 56 | ez_libc.c \ 57 | fsckdns.c \ 58 | str.c \ 59 | util.c \ 60 | 61 | # libs := z crypto GeoIP pthread 62 | endif 63 | 64 | ######################################## 65 | # Set up custom compile flags here. # 66 | ######################################## 67 | ifeq ($(version),debug) 68 | local_cppflags := $(local_cppflags) -D_DEBUG -DDEBUG -std=gnu99 69 | local_codeflags := -g2 -O0 -Wreturn-type -Wformat -Wchar-subscripts -Wparentheses -Wcast-qual -Wmissing-declarations 70 | local_ldflags := $(local_ldflags) -L$(libsDir)/$(version) 71 | endif 72 | 73 | ifeq ($(version),release) 74 | local_cppflags := $(local_cppflags) -DNDEBUG -std=gnu99 75 | local_codeflags := -g0 -O3 -Wreturn-type -Wformat -Wchar-subscripts -Wparentheses -Wcast-qual -Wmissing-declarations 76 | local_ldflags := $(local_ldflags) -L$(libsDir)/$(version) 77 | endif 78 | 79 | -------------------------------------------------------------------------------- /iptables.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef IPTABLES_H 20 | #define IPTABLES_H 21 | 22 | #include "ptrvec.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | int 29 | IPTABLES_is_currently_blocked(const char *addr); 30 | /******************************************************** 31 | * This provides an efficient lookup of addresses blocked 32 | * by iptables in the filter table, INPUT chain. 33 | * 34 | * RETURN: 35 | * 1 if the supplied addr is blocked by iptables. 36 | * 0 otherwise. 37 | */ 38 | 39 | int 40 | IPTABLES_block_addresses(PTRVEC *h_vec); 41 | /************************************************************** 42 | * Block addresses. 43 | */ 44 | 45 | int 46 | IPTABLES_unblock_addresses(PTRVEC *h_vec); 47 | /************************************************************** 48 | * Unblock addresses. 49 | */ 50 | 51 | int 52 | IPTABLES_fill_in_missing(MAP *h_rtn_map); 53 | /************************************************************** 54 | * Fill in all blocked IP's which are not already in *h_map. 55 | */ 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | 61 | #endif 62 | 63 | -------------------------------------------------------------------------------- /ez_libanl.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef EZ_LIBANL_H 20 | #define EZ_LIBANL_H 21 | 22 | /* Simplified interface to libanl functions */ 23 | #ifndef _GNU_SOURCE 24 | # define _GNU_SOURCE 25 | #endif 26 | #include 27 | #include "ez.h" 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | ez_proto(int, getaddrinfo_a, 34 | int mode, 35 | struct gaicb *list[], 36 | int nitems, 37 | struct sigevent *sevp); 38 | #ifdef DEBUG 39 | # define ez_getaddrinfo_a(...) \ 40 | _ez_getaddrinfo_a(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 41 | #else 42 | # define ez_getaddrinfo_a(...) \ 43 | _ez_getaddrinfo_a(__VA_ARGS__) 44 | #endif 45 | 46 | ez_proto (int, gai_suspend, 47 | const struct gaicb * const list[], 48 | int nitems, 49 | const struct timespec *timeout); 50 | #ifdef DEBUG 51 | # define ez_gai_suspend(...) \ 52 | _ez_gai_suspend(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 53 | #else 54 | # define ez_gai_suspend(...) \ 55 | _ez_gai_suspend(__VA_ARGS__) 56 | #endif 57 | 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /timestamp.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef TIMESTAMP_H 20 | #define TIMESTAMP_H 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | #include 25 | #include 26 | 27 | #include "cfgmap.h" 28 | 29 | typedef struct _TS { 30 | const char *pattern; 31 | regex_t re; 32 | const char *strptime_fmt; 33 | int64_t flags; 34 | } TS; 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | #define TS_is_prepared(s) \ 41 | ((s)->pattern ? 1 : 0) 42 | 43 | int 44 | TS_init(TS *self, CFGMAP *h_map, const char *pfix); 45 | /******************************************************** 46 | * Initialize timestamp from config map. 47 | */ 48 | 49 | void* 50 | TS_destructor(TS *self); 51 | /******************************************************** 52 | * Free resources. 53 | */ 54 | 55 | int 56 | TS_scan(const TS *self, time_t *rslt, const char *str, const struct tm *pTmRef); 57 | /******************************************************** 58 | * Scan a string to obtain the timestamp. 59 | */ 60 | 61 | int 62 | TS_MD5_update(const TS *self, MD5_CTX *ctx); 63 | /******************************************************** 64 | * For computing MD5 checksum of config data. 65 | */ 66 | 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /target.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef TARGET_H 20 | #define TARGET_H 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | #include "cfgmap.h" 25 | 26 | struct TargetRx { 27 | const char *pattern; 28 | regex_t re; 29 | }; 30 | 31 | typedef struct _Target { 32 | enum { 33 | TARGET_INIT_FLG=1<<0 34 | } flags; 35 | unsigned severity, 36 | nRx; 37 | struct TargetRx *rxArr; 38 | } Target; 39 | 40 | #define Target_severity(s) \ 41 | ((const unsigned)(s)->severity) 42 | 43 | #define Target_is_init(s) \ 44 | ((const int)(s)->flags) 45 | 46 | 47 | #ifdef __cplusplus 48 | extern "C" { 49 | #endif 50 | 51 | int 52 | Target_init(Target *self, CFGMAP *h_map, const char *pfix); 53 | /******************************************************** 54 | * Prepare for use from config map 55 | */ 56 | 57 | void* 58 | Target_destructor(Target *self); 59 | /******************************************************** 60 | * Free resources. 61 | */ 62 | 63 | int 64 | Target_scan(const Target *self, char *rsltBuf, unsigned buf_sz, const char *str); 65 | /******************************************************** 66 | * Scan a string to obtain the address. 67 | */ 68 | 69 | int 70 | Target_MD5_update(const Target *self, MD5_CTX *ctx); 71 | /******************************************************** 72 | * For computing MD5 checksum of cumulative patterns. 73 | */ 74 | 75 | 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | #endif 82 | 83 | -------------------------------------------------------------------------------- /cntry.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #include 20 | #include 21 | 22 | #include "ban2fail.h" 23 | #include "cntry.h" 24 | #include "map.h" 25 | #include "util.h" 26 | 27 | /*==================================================================*/ 28 | /*=================== Local static data ============================*/ 29 | /*==================================================================*/ 30 | static struct { 31 | 32 | int is_init; 33 | GeoIP *gip, 34 | *gip6; 35 | 36 | } S; 37 | 38 | static void 39 | init() 40 | /******************************************************** 41 | * Perform any 1 time initialization. 42 | */ 43 | { 44 | /* Note that initialization has happened */ 45 | S.is_init= 1; 46 | 47 | /* Open the GeoIP database */ 48 | S.gip= GeoIP_open(GEOIP_DB, 0); 49 | if(!S.gip) { 50 | eprintf("PANIC: GeoIP_open(\"%s\") failed!", GEOIP_DB); 51 | exit(EXIT_FAILURE); 52 | } 53 | 54 | S.gip6= GeoIP_open(GEOIP6_DB, 0); 55 | if(!S.gip6) { 56 | eprintf("PANIC: GeoIP_open(\"%s\") failed!", GEOIP6_DB); 57 | exit(EXIT_FAILURE); 58 | } 59 | } 60 | 61 | const char* 62 | COUNTRY_get_code(const char *addr) 63 | /******************************************************** 64 | * Try to get the country code. 65 | */ 66 | { 67 | if(!S.is_init) init(); 68 | 69 | if(strchr(addr, ':')) 70 | return GeoIP_country_code_by_addr_v6(S.gip6, addr); 71 | 72 | return GeoIP_country_code_by_addr(S.gip, addr); 73 | } 74 | 75 | -------------------------------------------------------------------------------- /addrRpt.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef AddrRPT_H 20 | #define AddrRPT_H 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | 25 | #include "logFile.h" 26 | #include "ptrvec.h" 27 | 28 | /* One of these for each offense found in a log file */ 29 | typedef struct _AddrRPT { 30 | 31 | unsigned serial; 32 | 33 | char addr[46]; 34 | 35 | /* Store vector of match objects */ 36 | PTRVEC match_vec; 37 | 38 | } AddrRPT; 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | #define AddrRPT_addr_create(p, addr) \ 45 | ((p)=(AddrRPT_addr_constructor((p)=malloc(sizeof(AddrRPT)), addr) ? (p) : ( p ? realloc(AddrRPT_destructor(p),0) : 0 ))) 46 | AddrRPT* 47 | AddrRPT_addr_constructor(AddrRPT *self, const char *addr); 48 | /******************************************************** 49 | * Prepare for use from an address on the command line 50 | */ 51 | 52 | #define AddrRPT_destroy(s) \ 53 | {if(AddrRPT_destructor(s)) {free(s); (s)=0;}} 54 | void* 55 | AddrRPT_destructor(AddrRPT *self); 56 | /******************************************************** 57 | * Free resources. 58 | */ 59 | 60 | int 61 | AddrRPT_addLine(AddrRPT *self, LOGFILE *lf, const char *line); 62 | /******************************************************** 63 | * Add a matching line to this object. 64 | */ 65 | 66 | int 67 | AddrRPT_print(AddrRPT *self, FILE *fh); 68 | /******************************************************** 69 | * Print a human readable representation of *self. 70 | */ 71 | 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif 78 | 79 | -------------------------------------------------------------------------------- /ez_libanl.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #define _GNU_SOURCE 20 | #include 21 | 22 | #include "util.h" 23 | #include "ez_libanl.h" 24 | 25 | /***************************************************/ 26 | int _ez_getaddrinfo_a( 27 | #ifdef DEBUG 28 | const char *fileName, 29 | int lineNo, 30 | const char *funcName, 31 | #endif 32 | int mode, 33 | struct gaicb *list[], 34 | int nitems, 35 | struct sigevent *sevp 36 | ) 37 | { 38 | errno= 0; 39 | int rtn= getaddrinfo_a (mode, list, nitems, sevp); 40 | switch(rtn) { 41 | case 0: 42 | case EAI_AGAIN: 43 | return rtn; 44 | } 45 | 46 | /* _sys_eprintf() will pass errno to gai_sterror */ 47 | errno= rtn; 48 | _sys_eprintf(gai_strerror 49 | #ifdef DEBUG 50 | , fileName, lineNo, funcName 51 | #endif 52 | , "getaddrinfo_a() failed"); 53 | abort(); 54 | } 55 | 56 | /***************************************************/ 57 | int _ez_gai_suspend( 58 | #ifdef DEBUG 59 | const char *fileName, 60 | int lineNo, 61 | const char *funcName, 62 | #endif 63 | const struct gaicb * const list[], 64 | int nitems, 65 | const struct timespec *timeout 66 | ) 67 | { 68 | errno= 0; 69 | int rtn= gai_suspend (list, nitems, timeout); 70 | switch(rtn) { 71 | case 0: 72 | case EAI_AGAIN: 73 | case EAI_ALLDONE: 74 | case EAI_INTR: 75 | return rtn; 76 | } 77 | 78 | /* _sys_eprintf() will pass errno to gai_sterror */ 79 | errno= rtn; 80 | _sys_eprintf(gai_strerror 81 | #ifdef DEBUG 82 | , fileName, lineNo, funcName 83 | #endif 84 | , "gai_suspend() failed"); 85 | abort(); 86 | } 87 | -------------------------------------------------------------------------------- /ban2fail.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # JDR Wed 27 Nov 2019 01:30:29 PM EST 4 | # The purpose of this script is to be run from a systemd service 5 | # file, or sysvinit script. 6 | # 7 | # BE CAREFUL not to monitor the log file to which output from this 8 | # script is written - you will have a feedback loop! 9 | # 10 | 11 | BAN2FAIL_CFG=/etc/ban2fail/ban2fail.cfg 12 | INOTIFYWAIT=/usr/bin/inotifywait 13 | BAN2FAIL=/usr/local/bin/ban2fail 14 | 15 | # For testing only 16 | #BAN2FAIL="/usr/local/bin/ban2fail -t $BAN2FAIL_CFG" 17 | 18 | # Uncomment this if you wish to see output from the time command 19 | #TIME=time 20 | 21 | # Do not run again for at least this many deciseconds, to 22 | # avoid monopolizing CPU 23 | MIN_PERIOD_DS=3 24 | 25 | # Get period in nanoseconds for integer calculations 26 | (( MIN_PERIOD_NS = MIN_PERIOD_DS * 100000000 )) 27 | 28 | while true; do 29 | echo "Starting main loop" 30 | MON_FNAMES=$($BAN2FAIL --print-lfn | tr $'\n' ' ') 31 | MON_FNAMES="$MON_FNAMES $BAN2FAIL_CFG" 32 | 33 | # Always do initial check 34 | echo "Initial run for $BAN2FAIL" 35 | RAN_NS=$(date +%s%N) 36 | $TIME $BAN2FAIL 37 | 38 | echo "Monitoring: $MON_FNAMES" 39 | 40 | # Launch inotifywait in the background outputting to fd #3 41 | exec 3< <(exec $INOTIFYWAIT -m $MON_FNAMES) 42 | INOTIFYWAIT_PID=$! 43 | 44 | # Read the output of inotifywait 45 | while read -u 3 FILE OPS; do 46 | 47 | case "$OPS" in 48 | MOVE_SELF) break;; 49 | 50 | MODIFY) [[ "$FILE" == $BAN2FAIL_CFG ]] && break;; 51 | 52 | *) continue;; 53 | esac 54 | 55 | # Uncomment this to see the inotifywait output which triggered this cycle 56 | #echo "FILE= '$FILE', OPS= '$OPS'" 57 | 58 | NOW_NS=$(date +%s%N) 59 | (( SINCE_NS = NOW_NS - RAN_NS )) 60 | 61 | if (( SINCE_NS < MIN_PERIOD_NS )); then 62 | 63 | (( REMAINING_NS = MIN_PERIOD_NS - SINCE_NS )) 64 | 65 | # 'sleep' command wants a string representation of floating point number of seconds, 66 | # so we need to break sleep time into seconds and nanosecond remainder components 67 | (( REMAINING_SEC = REMAINING_NS / 1000000000 )) 68 | (( REMAINING_NS_REM = REMAINING_NS % 1000000000 )) 69 | 70 | if (( REMAINING_SEC || REMAINING_NS_REM > 1000000 )); then 71 | 72 | # use printf command to format as floating point string 73 | REMAINING_SEC_FP=$(printf '%d.%09d' $REMAINING_SEC $REMAINING_NS_REM) 74 | 75 | # sleep for floating point period of seconds 76 | sleep $REMAINING_SEC_FP 77 | fi 78 | fi 79 | 80 | echo "Running $BAN2FAIL" 81 | 82 | # Here is where we check for offenses. 83 | # If ban2fail fails it is probably because logrotated 84 | # is managing the log files, so bail out... 85 | RAN_NS=$(date +%s%N) 86 | $TIME $BAN2FAIL || break 87 | 88 | done 89 | 90 | # Shut down inotifywait 91 | if ps $INOTIFYWAIT_PID &>/dev/null; then 92 | kill $INOTIFYWAIT_PID 93 | wait 94 | fi 95 | exec 3<&- 96 | 97 | echo 'Exiting main loop' 98 | # Pause to let things settle down 99 | sleep 1 100 | 101 | done 102 | 103 | 104 | exit 0 105 | -------------------------------------------------------------------------------- /fsckdns.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #define _GNU_SOURCE 20 | #include 21 | #include 22 | #include 23 | 24 | #include "ez_libc.h" 25 | #include "util.h" 26 | const static struct addrinfo rev_hints= { 27 | .ai_flags = AI_NUMERICHOST, /* doing reverse lookups */ 28 | .ai_family = AF_UNSPEC, /* Allow IPv4 or IPv6 */ 29 | .ai_socktype= SOCK_DGRAM, 30 | .ai_protocol= IPPROTO_UDP 31 | }; 32 | 33 | const static struct addrinfo fwd_hints= { 34 | .ai_family= AF_UNSPEC, /* Allow IPv4 or IPv6 */ 35 | .ai_socktype= SOCK_DGRAM, 36 | .ai_protocol= IPPROTO_UDP 37 | }; 38 | 39 | int 40 | main(int argc, char **argv) 41 | { 42 | int rtn= EXIT_FAILURE; 43 | const char *addr= NULL; 44 | static char hostBuf[PATH_MAX]; 45 | 46 | extern char *optarg; 47 | extern int optind, optopt; 48 | 49 | for(optind= 1; optind < argc; ++optind) 50 | { 51 | addr= argv[optind]; 52 | 53 | /*============ Reverse DNS lookup ================*/ 54 | /* Get a populated addrinfo object */ 55 | struct addrinfo *res= NULL; 56 | int rc= ez_getaddrinfo(addr, NULL, &rev_hints, &res); 57 | assert(0 == rc); 58 | assert(res && res->ai_addr && res->ai_addrlen); 59 | addrinfo_print(res, stdout); 60 | ez_fflush(stdout); 61 | 62 | /* Now do blocking reverse lookup */ 63 | rc= ez_getnameinfo(res->ai_addr, res->ai_addrlen, hostBuf, sizeof(hostBuf)-1, NULL, 0, NI_NAMEREQD); 64 | if(rc) { 65 | ez_fprintf(stdout, "%s\n", gai_strerror(rc)); 66 | continue; 67 | } 68 | 69 | ez_fprintf(stdout, "RevDNS= \"%s\"\n", hostBuf); 70 | ez_fflush(stdout); 71 | 72 | /*============ Forward DNS lookup ================*/ 73 | rc= ez_getaddrinfo(hostBuf, NULL, &fwd_hints, &res); 74 | const char *msg= NULL; 75 | 76 | if(rc) { 77 | ez_fprintf(stdout, "%s\n", gai_strerror(rc)); 78 | continue; 79 | } 80 | 81 | addrinfo_print(res, stdout); 82 | ez_fflush(stdout); 83 | 84 | } 85 | 86 | rtn= EXIT_SUCCESS; 87 | abort: 88 | return rtn; 89 | } 90 | -------------------------------------------------------------------------------- /pdns.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | /* 20 | * JDR Sat 30 Nov 2019 08:27:23 AM EST 21 | * Performs DNS reverse + fwd lookups in parallel. Having to use a bunch of threads 22 | * to overcome the serialization inherent in blocking calls is a travesty, but 23 | * I couldn't find a non-blocking version of getnameinfo(). 24 | * 25 | * Oh yeah, and I'm not in the mood to write it myself ;-) 26 | */ 27 | 28 | #ifndef PARALLEL_DNS_H 29 | #define PARALLEL_DNS_H 30 | 31 | 32 | /* Number of threads to use in parallel */ 33 | #define PDNS_MAX_THREADS 200 34 | /* Size manager's inbox to avoid overflow */ 35 | #define PDNS_MGR_INBOX_SZ PDNS_MAX_THREADS*2 36 | #define PDNS_WORKER_INBOX_SZ 1 37 | /* Give worker threads a chance to join */ 38 | #define PDNS_SHUTDOWN_PAUSE_MS 500 39 | 40 | enum PDNS_flags { 41 | PDNS_SERVFAIL_FLG= 1<<0, 42 | PDNS_NXDOMAIN_FLG= 1<<1, 43 | PDNS_REV_DNS_FLG= 1<<2, 44 | PDNS_FWD_DNS_FLG= 1<<3, 45 | PDNS_FWD_FAIL_FLG= 1<<4, 46 | PDNS_FWD_NONE_FLG= 1<<5, 47 | PDNS_FWD_MISMATCH_FLG= 1<<6, 48 | PDNS_DONE_MASK= PDNS_SERVFAIL_FLG|PDNS_NXDOMAIN_FLG|PDNS_FWD_DNS_FLG, 49 | PDNS_BAD_MASK= PDNS_SERVFAIL_FLG| 50 | PDNS_NXDOMAIN_FLG| 51 | PDNS_FWD_FAIL_FLG| 52 | PDNS_FWD_NONE_FLG| 53 | PDNS_FWD_MISMATCH_FLG 54 | 55 | }; 56 | 57 | #define _GNU_SOURCE 58 | #include "offEntry.h" 59 | 60 | #ifdef __cplusplus 61 | extern "C" { 62 | #endif 63 | 64 | /* Fix recursive #include dependency */ 65 | struct _OFFENTRY; 66 | 67 | int 68 | PDNS_lookup(struct _OFFENTRY *lePtrArr[], unsigned nItems, unsigned timeout_ms); 69 | /************************************************************** 70 | * Perform parallel DNS reverse lookups on all OFFENTRY objects 71 | * referenced in lePtrArr until finished, or timeout_ms has lapsed. 72 | * 73 | * lePtrArr: array of pointers to OFFENTRY objects 74 | * nItems: length of array 75 | * timeout_ms: maximum amount of time to spend performing lookups. 76 | * 77 | * RETURNS 78 | * suceess - number of lookups completed 79 | * -1 Failures 80 | */ 81 | 82 | #ifdef __cplusplus 83 | } 84 | #endif 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /obsvTpl.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef OBSVTPL_H 20 | #define OBSVTPL_H 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | #include 25 | #include 26 | 27 | #include "addrRpt.h" 28 | #include "dynstack.h" 29 | #include "logFile.h" 30 | 31 | typedef struct _ObsvTpl { 32 | char addr[43]; 33 | LOGFILE *lf; 34 | DS stack; 35 | } ObsvTpl; 36 | 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | #define ObsvTpl_create(p, lf, addr) \ 43 | ((p)=(ObsvTpl_constructor((p)=malloc(sizeof(ObsvTpl)), lf, addr) ? (p) : ( p ? realloc(ObsvTpl_destructor(p),0) : 0 ))) 44 | ObsvTpl* 45 | ObsvTpl_constructor(ObsvTpl *self, LOGFILE *lf, const char *addr); 46 | /******************************************************** 47 | * Prepare for use from an address on the command line 48 | */ 49 | 50 | int 51 | ObsvTpl_sinit(ObsvTpl *self, LOGFILE *lf, const char *addr); 52 | /******************************************************** 53 | * Initialize or reset a static instance 54 | */ 55 | 56 | #define ObsvTpl_destroy(s) \ 57 | {if(ObsvTpl_destructor(s)) {free(s); (s)=0;}} 58 | void* 59 | ObsvTpl_destructor(ObsvTpl *self); 60 | /******************************************************** 61 | * Free resources. 62 | */ 63 | 64 | int 65 | ObsvTpl_addObsv(ObsvTpl *self, z_off_t pos, unsigned len); 66 | /***************************************************************** 67 | * Add an observation to this object. 68 | */ 69 | 70 | int 71 | ObsvTpl_db_get(ObsvTpl *self, DB *db); 72 | /******************************************************** 73 | * Fetch our content from a database. 74 | */ 75 | 76 | int 77 | ObsvTpl_db_put(ObsvTpl *self, DB *db); 78 | /***************************************************************** 79 | * Write our contents into the database. 80 | */ 81 | 82 | int 83 | ObsvTpl_put_AddrRPT(ObsvTpl *self, gzFile fh, AddrRPT *ar); 84 | /******************************************************** 85 | * Place contents of self into ar. 86 | */ 87 | 88 | int 89 | ObsvTpl_print(ObsvTpl *self, FILE *fh); 90 | /******************************************************** 91 | * Print a human readable representation of *self. 92 | */ 93 | 94 | 95 | #ifdef __cplusplus 96 | } 97 | #endif 98 | 99 | #endif 100 | 101 | -------------------------------------------------------------------------------- /ez_libpthread.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef EZ_LIBPTHREAD_H 20 | #define EZ_LIBPTHREAD_H 21 | 22 | /* Simplified interface to libpthread functions */ 23 | #ifndef _GNU_SOURCE 24 | # define _GNU_SOURCE 25 | #endif 26 | #include 27 | 28 | #include "ez.h" 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | ez_proto (int, pthread_mutex_lock, 35 | pthread_mutex_t *mutex); 36 | #ifdef DEBUG 37 | # define ez_pthread_mutex_lock(...) \ 38 | _ez_pthread_mutex_lock(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 39 | #else 40 | # define ez_pthread_mutex_lock(...) \ 41 | _ez_pthread_mutex_lock(__VA_ARGS__) 42 | #endif 43 | 44 | ez_proto (int, pthread_mutex_unlock, 45 | pthread_mutex_t *mutex); 46 | #ifdef DEBUG 47 | # define ez_pthread_mutex_unlock(...) \ 48 | _ez_pthread_mutex_unlock(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 49 | #else 50 | # define ez_pthread_mutex_unlock(...) \ 51 | _ez_pthread_mutex_unlock(__VA_ARGS__) 52 | #endif 53 | 54 | ez_proto (int, pthread_create, 55 | pthread_t *thread, 56 | const pthread_attr_t *attr, 57 | void *(*start_routine) (void *), 58 | void *arg); 59 | #ifdef DEBUG 60 | # define ez_pthread_create(...) \ 61 | _ez_pthread_create(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 62 | #else 63 | # define ez_pthread_create(...) \ 64 | _ez_pthread_create(__VA_ARGS__) 65 | #endif 66 | 67 | ez_proto (int, pthread_cond_signal, 68 | pthread_cond_t *cond); 69 | #ifdef DEBUG 70 | # define ez_pthread_cond_signal(...) \ 71 | _ez_pthread_cond_signal(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 72 | #else 73 | # define ez_pthread_cond_signal(...) \ 74 | _ez_pthread_cond_signal(__VA_ARGS__) 75 | #endif 76 | 77 | ez_proto (int, pthread_cond_wait, 78 | pthread_cond_t *cond, 79 | pthread_mutex_t *mutex); 80 | #ifdef DEBUG 81 | # define ez_pthread_cond_wait(...) \ 82 | _ez_pthread_cond_wait(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 83 | #else 84 | # define ez_pthread_cond_wait(...) \ 85 | _ez_pthread_cond_wait(__VA_ARGS__) 86 | #endif 87 | 88 | ez_proto (int, pthread_join, 89 | pthread_t thread, 90 | void **retval); 91 | #ifdef DEBUG 92 | # define ez_pthread_join(...) \ 93 | _ez_pthread_join(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 94 | #else 95 | # define ez_pthread_join(...) \ 96 | _ez_pthread_join(__VA_ARGS__) 97 | #endif 98 | 99 | #ifdef __cplusplus 100 | } 101 | #endif 102 | 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /dynstack.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | 20 | #ifndef DS_H 21 | #define DS_H 22 | 23 | typedef struct _DS { 24 | unsigned size, 25 | count, 26 | elsize; 27 | char *stk_ptr; 28 | } DS; 29 | 30 | 31 | #define DS_currBuf_sz(s) \ 32 | ((const unsigned)(s)->size) 33 | 34 | #define DS_numItems(s)\ 35 | ((const unsigned)(s)->count) 36 | /* Return the number of items currently on the stack */ 37 | 38 | #define DS_ptr(s)\ 39 | ((void*)(s)->stk_ptr) 40 | /* Return the stack pointer */ 41 | 42 | #define DS_qsort(s, cmp_func)\ 43 | qsort((s)->stk_ptr, (s)->count, (s)->elsize, cmp_func) 44 | /* Sort the stack using qsort() */ 45 | 46 | #define DS_reset(s) \ 47 | ((s)->count= 0) 48 | /* Reset the stack so that no items are contained */ 49 | 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | #define DS_create(p, elmtSize, numElmts) \ 56 | ((p)= (DS_constructor((p)=malloc(sizeof(DS)), elmtSize, numElmts) ? (p) : ( p ? realloc(DS_destructor(p),0) : 0 ))) 57 | DS* 58 | DS_constructor(DS *self, unsigned int elmtSize, unsigned int numElmts); 59 | /* Initialize the dynamic stack object. You must provide the 60 | * size of the elements (in bytes) you wish to use the stack for, and 61 | * the approximate max number of element you think you will use. 62 | */ 63 | 64 | int 65 | DS_sinit(DS *self, unsigned int elmtSize, unsigned int numElmts); 66 | /* Initializion for static instance of DS. Initializes once per 67 | * process, and reset() all other times. 68 | */ 69 | 70 | #define DS_destroy(s) \ 71 | {if(DS_destructor(s)) {free(s);s=0;}} 72 | void* 73 | DS_destructor(DS *self); 74 | /* Close the dynamic stack, free all memory, etc. */ 75 | 76 | 77 | int 78 | DS_top(DS *self, void *dest_ptr); 79 | /* Copy the element at the top of the stack to the dest_ptr buffer 80 | * area. 81 | */ 82 | 83 | int 84 | DS_pop(DS *self, void *dest_ptr); 85 | /* Pop the top element off the stack and copy it to the dest_ptr 86 | * buffer area 87 | */ 88 | 89 | int 90 | DS_push(DS *self, const void *src_ptr); 91 | /* Push a new element on the top of the stack. */ 92 | 93 | int 94 | DS_entry_exists(const DS *self, const void *target_ptr); 95 | /* Return true if the item exists in the stack */ 96 | 97 | int 98 | DS_visitAllEntries(DS *self, int (* func)(void *item_ptr, void *data), void *data); 99 | /****************************************************************************** 100 | * Visit all entries in the stack. if (*func) returns nonzero, then 101 | * the process stops and DS_visitAllEntries will return non-zero. 102 | */ 103 | 104 | #ifdef __cplusplus 105 | } 106 | #endif 107 | #endif /* DS_H */ 108 | -------------------------------------------------------------------------------- /ez_libz.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef EZ_GZFILE_H 20 | #define EZ_GZFILE_H 21 | 22 | /* Simplified interface to libz file functions */ 23 | #ifndef _GNU_SOURCE 24 | # define _GNU_SOURCE 25 | #endif 26 | #include 27 | 28 | #include "ez.h" 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | ez_proto (gzFile, gzopen, 35 | const char *path, 36 | const char *mode); 37 | #ifdef DEBUG 38 | # define ez_gzopen(...) \ 39 | _ez_gzopen(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 40 | #else 41 | # define ez_gzopen(...) \ 42 | _ez_gzopen(__VA_ARGS__) 43 | #endif 44 | 45 | ez_proto (int, gzclose, 46 | gzFile file); 47 | #ifdef DEBUG 48 | # define ez_gzclose(...) \ 49 | _ez_gzclose(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 50 | #else 51 | # define ez_gzclose(...) \ 52 | _ez_gzclose(__VA_ARGS__) 53 | #endif 54 | 55 | ez_proto (int, gzwrite, 56 | gzFile file, 57 | voidpc buf, 58 | unsigned len); 59 | #ifdef DEBUG 60 | # define ez_gzwrite(...) \ 61 | _ez_gzwrite(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 62 | #else 63 | # define ez_gzwrite(...) \ 64 | _ez_gzwrite(__VA_ARGS__) 65 | #endif 66 | 67 | ez_proto (int, gzread, 68 | gzFile file, 69 | voidp buf, 70 | unsigned len); 71 | #ifdef DEBUG 72 | # define ez_gzread(...) \ 73 | _ez_gzread(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 74 | #else 75 | # define ez_gzread(...) \ 76 | _ez_gzread(__VA_ARGS__) 77 | #endif 78 | 79 | ez_proto (int, gzflush, 80 | gzFile file, 81 | int flush); 82 | #ifdef DEBUG 83 | # define ez_gzflush(...) \ 84 | _ez_gzflush(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 85 | #else 86 | # define ez_gzflush(...) \ 87 | _ez_gzflush(__VA_ARGS__) 88 | #endif 89 | 90 | ez_proto (z_off_t, gzseek, 91 | gzFile file, 92 | z_off_t offset, 93 | int whence); 94 | #ifdef DEBUG 95 | # define ez_gzseek(...) \ 96 | _ez_gzseek(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 97 | #else 98 | # define ez_gzseek(...) \ 99 | _ez_gzseek(__VA_ARGS__) 100 | #endif 101 | 102 | ez_proto (z_off_t, gztell, 103 | gzFile file); 104 | #ifdef DEBUG 105 | # define ez_gztell(...) \ 106 | _ez_gztell(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 107 | #else 108 | # define ez_gztell(...) \ 109 | _ez_gztell(__VA_ARGS__) 110 | #endif 111 | 112 | ez_proto (char*, gzgets, 113 | gzFile file, 114 | char *buf, 115 | int len); 116 | #ifdef DEBUG 117 | # define ez_gzgets(...) \ 118 | _ez_gzgets(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 119 | #else 120 | # define ez_gzgets(...) \ 121 | _ez_gzgets(__VA_ARGS__) 122 | #endif 123 | 124 | #ifdef __cplusplus 125 | } 126 | #endif 127 | 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /ez_libdb.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef EZ_LIBDB_H 20 | #define EZ_LIBDB_H 21 | 22 | /* Simplified interface to libanl functions */ 23 | #ifndef _GNU_SOURCE 24 | # define _GNU_SOURCE 25 | #endif 26 | #include 27 | 28 | #include "ez.h" 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | ez_proto (int, db_create, 35 | DB **dbp, 36 | DB_ENV *dbenv, 37 | u_int32_t flags); 38 | #ifdef DEBUG 39 | # define ez_db_create(...) \ 40 | _ez_db_create(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 41 | #else 42 | # define ez_db_create(...) \ 43 | _ez_db_create(__VA_ARGS__) 44 | #endif 45 | 46 | ez_proto (int, db_open, 47 | DB *db, 48 | DB_TXN *txnid, 49 | const char *file, 50 | const char *database, 51 | DBTYPE type, 52 | u_int32_t flags, 53 | int mode); 54 | #ifdef DEBUG 55 | # define ez_db_open(...) \ 56 | _ez_db_open(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 57 | #else 58 | # define ez_db_open(...) \ 59 | _ez_db_open(__VA_ARGS__) 60 | #endif 61 | 62 | ez_proto (int, db_put, 63 | DB *db, 64 | DB_TXN *txnid, 65 | DBT *key, 66 | DBT *data, 67 | u_int32_t flags); 68 | #ifdef DEBUG 69 | # define ez_db_put(...) \ 70 | _ez_db_put(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 71 | #else 72 | # define ez_db_put(...) \ 73 | _ez_db_put(__VA_ARGS__) 74 | #endif 75 | 76 | ez_proto (int, db_get, 77 | DB *db, 78 | DB_TXN *txnid, 79 | DBT *key, 80 | DBT *data, 81 | u_int32_t flags); 82 | #ifdef DEBUG 83 | # define ez_db_get(...) \ 84 | _ez_db_get(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 85 | #else 86 | # define ez_db_get(...) \ 87 | _ez_db_get(__VA_ARGS__) 88 | #endif 89 | 90 | ez_proto (int, db_del, 91 | DB *db, 92 | DB_TXN *txnid, 93 | DBT *key, 94 | u_int32_t flags); 95 | #ifdef DEBUG 96 | # define ez_db_del(...) \ 97 | _ez_db_del(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 98 | #else 99 | # define ez_db_del(...) \ 100 | _ez_db_del(__VA_ARGS__) 101 | #endif 102 | 103 | ez_proto (int, db_close, 104 | DB *db, 105 | u_int32_t flags); 106 | #ifdef DEBUG 107 | # define ez_db_close(...) \ 108 | _ez_db_close(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 109 | #else 110 | # define ez_db_close(...) \ 111 | _ez_db_close(__VA_ARGS__) 112 | #endif 113 | 114 | ez_proto (int, db_fd, 115 | DB *db, 116 | int *fdp); 117 | #ifdef DEBUG 118 | # define ez_db_fd(...) \ 119 | _ez_db_fd(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 120 | #else 121 | # define ez_db_fd(...) \ 122 | _ez_db_fd(__VA_ARGS__) 123 | #endif 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /ez_libpthread.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | 20 | #define _GNU_SOURCE 21 | #include 22 | #include 23 | 24 | #include "ez_libpthread.h" 25 | #include "util.h" 26 | 27 | /***************************************************/ 28 | ez_proto (int, pthread_mutex_lock, pthread_mutex_t *mutex) 29 | { 30 | int rtn= pthread_mutex_lock (mutex); 31 | if(0 == rtn) return 0; 32 | 33 | errno= rtn; 34 | _sys_eprintf((const char*(*)(int))strerror 35 | #ifdef DEBUG 36 | , fileName, lineNo, funcName 37 | #endif 38 | , "pthread_mutex_lock() failed"); 39 | abort(); 40 | } 41 | 42 | /***************************************************/ 43 | ez_proto (int, pthread_mutex_unlock, pthread_mutex_t *mutex) 44 | { 45 | int rtn= pthread_mutex_unlock (mutex); 46 | if(0 == rtn) return 0; 47 | 48 | errno= rtn; 49 | _sys_eprintf((const char*(*)(int))strerror 50 | #ifdef DEBUG 51 | , fileName, lineNo, funcName 52 | #endif 53 | , "pthread_mutex_unlock() failed"); 54 | abort(); 55 | } 56 | 57 | /***************************************************/ 58 | ez_proto (int, pthread_create, 59 | pthread_t *thread, 60 | const pthread_attr_t *attr, 61 | void *(*start_routine) (void *), 62 | void *arg) 63 | { 64 | int rtn= pthread_create (thread, attr, start_routine, arg); 65 | if(0 == rtn) return 0; 66 | 67 | errno= rtn; 68 | _sys_eprintf((const char*(*)(int))strerror 69 | #ifdef DEBUG 70 | , fileName, lineNo, funcName 71 | #endif 72 | , "pthread_mutex_create() failed"); 73 | abort(); 74 | } 75 | 76 | /***************************************************/ 77 | ez_proto (int, pthread_cond_signal, pthread_cond_t *cond) 78 | { 79 | int rtn= pthread_cond_signal (cond); 80 | if(0 == rtn) return 0; 81 | 82 | errno= rtn; 83 | _sys_eprintf((const char*(*)(int))strerror 84 | #ifdef DEBUG 85 | , fileName, lineNo, funcName 86 | #endif 87 | , "pthread_cond_signal() failed"); 88 | abort(); 89 | } 90 | 91 | /***************************************************/ 92 | ez_proto (int, pthread_cond_wait, 93 | pthread_cond_t *cond, 94 | pthread_mutex_t *mutex) 95 | { 96 | int rtn= pthread_cond_wait (cond, mutex); 97 | if(0 == rtn) return 0; 98 | 99 | errno= rtn; 100 | _sys_eprintf((const char*(*)(int))strerror 101 | #ifdef DEBUG 102 | , fileName, lineNo, funcName 103 | #endif 104 | , "pthread_cond_wait() failed"); 105 | abort(); 106 | } 107 | 108 | /***************************************************/ 109 | ez_proto (int, pthread_join, 110 | pthread_t thread, 111 | void **retval) 112 | { 113 | int rtn= pthread_join (thread, retval); 114 | if(0 == rtn) return 0; 115 | 116 | errno= rtn; 117 | _sys_eprintf((const char*(*)(int))strerror 118 | #ifdef DEBUG 119 | , fileName, lineNo, funcName 120 | #endif 121 | , "pthread_join() failed"); 122 | abort(); 123 | } 124 | 125 | -------------------------------------------------------------------------------- /logType.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef LOGTYPE_H 20 | #define LOGTYPE_H 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | 25 | #include "ban2fail.h" 26 | #include "cfgmap.h" 27 | #include "map.h" 28 | #include "target.h" 29 | #include "timestamp.h" 30 | 31 | /*==================================================================*/ 32 | /*===================== log file prototype =========================*/ 33 | /*==================================================================*/ 34 | struct logProtoType { 35 | const char *dir, 36 | *pfix; 37 | TS ts; /* For log entry timestamps */ 38 | Target *targetArr; 39 | }; 40 | 41 | /*==================================================================*/ 42 | /*===================== LOGTYPE ====================================*/ 43 | /*==================================================================*/ 44 | /* One of these for each log file type to be scanned */ 45 | 46 | typedef struct _LOGTYPE { 47 | char *dir, 48 | *pfix, 49 | patterns_md5sum[33]; 50 | MAP file_map; 51 | } LOGTYPE; 52 | 53 | #ifdef __cplusplus 54 | extern "C" { 55 | #endif 56 | 57 | int 58 | LOGTYPE_init(CFGMAP *h_map, char *pfix); 59 | /************************************************************** 60 | * Initialize objects from configuration map. 61 | */ 62 | 63 | #define LOGTYPE_destroy(s) \ 64 | {if(LOGTYPE_destructor(s)) {free(s);(s)=0;}} 65 | LOGTYPE* 66 | LOGTYPE_destructor(LOGTYPE *self); 67 | /****************************************************************** 68 | * Free resources associated with a LOGTYPE object. 69 | */ 70 | 71 | const char* 72 | LOGTYPE_cacheName(const LOGTYPE *self); 73 | /****************************************************************** 74 | * Return in a static buffer the name of the cache directory which 75 | * will hold results for this log type. 76 | */ 77 | 78 | const char* 79 | LOGTYPE_fname_2_cacheName(const char *fname); 80 | /****************************************************************** 81 | * Return in a static buffer the name of the cache directory which 82 | * will hold results for the log type indicated by fname. 83 | */ 84 | 85 | int 86 | LOGTYPE_print(LOGTYPE *self, FILE *fh); 87 | /******************************************************** 88 | * Print a human readable representation of *self. 89 | */ 90 | 91 | int 92 | LOGTYPE_map_addr(LOGTYPE *self, MAP *h_rtnMap); 93 | /******************************************************** 94 | * Create a map of OFFENTRY objects with composite 95 | * counts by address. 96 | */ 97 | 98 | int 99 | LOGTYPE_offenseCount(LOGTYPE *self, unsigned *h_sum); 100 | /******************************************************** 101 | * Get a count of all offenses for this log type. 102 | */ 103 | 104 | int 105 | LOGTYPE_addressCount(LOGTYPE *self); 106 | /******************************************************** 107 | * Get a count of all addresses for this log type. 108 | */ 109 | 110 | #ifdef __cplusplus 111 | } 112 | #endif 113 | 114 | #endif /* LOGTYPE_H */ 115 | -------------------------------------------------------------------------------- /offEntry.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef OFFENTRY_H 20 | #define OFFENTRY_H 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | #include 25 | #include 26 | 27 | #include "map.h" 28 | #include "pdns.h" 29 | 30 | /* One of these for each offense found in a log file */ 31 | typedef struct _OFFENTRY { 32 | 33 | unsigned count, 34 | severity; 35 | 36 | time_t latest; 37 | 38 | char addr[46], 39 | cntry[3]; 40 | 41 | /* This data populated by PDNS_lookup() */ 42 | struct { 43 | enum PDNS_flags flags; 44 | char *name; 45 | } dns; 46 | 47 | } OFFENTRY; 48 | 49 | #if 0 50 | struct OFFENTRY_cacheWrite { 51 | FILE *fh; 52 | DB *dbh; 53 | }; 54 | #endif 55 | 56 | #ifdef __cplusplus 57 | extern "C" { 58 | #endif 59 | 60 | #define OFFENTRY_addr_create(p, addr) \ 61 | ((p)=(OFFENTRY_addr_constructor((p)=malloc(sizeof(OFFENTRY)), addr) ? (p) : ( p ? realloc(OFFENTRY_destructor(p),0) : 0 ))) 62 | OFFENTRY* 63 | OFFENTRY_addr_constructor(OFFENTRY *self, const char *addr); 64 | /******************************************************** 65 | * Prepare for use from an address found in a log entry. 66 | */ 67 | 68 | #define OFFENTRY_cache_create(p, cacheFileEntry) \ 69 | ((p)=(OFFENTRY_cache_constructor((p)=malloc(sizeof(OFFENTRY)), cacheFileEntry) ? (p) : ( p ? realloc(OFFENTRY_destructor(p),0) : 0 ))) 70 | OFFENTRY* 71 | OFFENTRY_cache_constructor(OFFENTRY *self, const char *cacheFileEntry); 72 | /******************************************************** 73 | * Prepare for use with entry from cache file. 74 | */ 75 | 76 | #define OFFENTRY_destroy(s) \ 77 | {if(OFFENTRY_destructor(s)) {free(s); (s)=0;}} 78 | void* 79 | OFFENTRY_destructor(OFFENTRY *self); 80 | /******************************************************** 81 | * Free resources. 82 | */ 83 | 84 | void 85 | OFFENTRY_register(OFFENTRY *self, unsigned severity, time_t when); 86 | /******************************************************** 87 | * Register the current failure try. 88 | */ 89 | 90 | int 91 | OFFENTRY_cacheWrite(OFFENTRY *self, FILE *fh); 92 | /******************************************************** 93 | * Write to the cache file in a form we can read later. 94 | */ 95 | 96 | int 97 | OFFENTRY_print(OFFENTRY *self, FILE *fh); 98 | /******************************************************** 99 | * Print a human readable representation of *self. 100 | */ 101 | 102 | int 103 | OFFENTRY_list(OFFENTRY *self, FILE *fh, int flags, unsigned nAllowed); 104 | /******************************************************** 105 | * Print in listing form 106 | */ 107 | 108 | int 109 | OFFENTRY_map_addr(OFFENTRY *self, MAP *h_rtnMap); 110 | /******************************************************** 111 | * Create a map of OFFENTRY objects with composite 112 | * counts by address. 113 | */ 114 | 115 | int 116 | OFFENTRY_offenseCount(OFFENTRY *self, unsigned *h_sum); 117 | /******************************************************** 118 | * Get a count of all offenses for this entry. 119 | */ 120 | 121 | #ifdef __cplusplus 122 | } 123 | #endif 124 | 125 | #endif 126 | 127 | -------------------------------------------------------------------------------- /ban2fail.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | /*************************************************************************************** 20 | * ban2fail global process declarations and data. 21 | ***************************************************************************************/ 22 | 23 | #ifndef BAN2FAIL_H 24 | #define BAN2FAIL_H 25 | 26 | #define _GNU_SOURCE 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "cfgmap.h" 33 | 34 | /* Maximum number of source ip addresses per iptables command. 35 | * I have not tested larger numbers, and it would probably 36 | * work with a much larger number. The command line maximum 37 | * is something like 200K characters. 38 | */ 39 | //#define IPTABLES_BATCH_SZ 100 40 | 41 | /* For sizing maps and vectors, this a starting point */ 42 | #define N_ADDRESSES_HINT 10000 43 | #define BUCKET_DEPTH_HINT 10 44 | 45 | #define MD5SUM_SZ 32 46 | 47 | /* How long to wait for reverse DNS lookups before giving up and 48 | * moving on with the report. 49 | */ 50 | #ifdef DEBUG 51 | # define DFLT_DNS_PAUSE_SEC 10 52 | #else 53 | # define DFLT_DNS_PAUSE_SEC 60 54 | #endif 55 | 56 | /* Where to find stuff */ 57 | #define CONFIGFILE "/etc/ban2fail/ban2fail.cfg" 58 | #define LOCKDIR "/run/lock/ban2fail" 59 | #define CACHEDIR "/var/cache/ban2fail" 60 | #define IPTABLES "/usr/sbin/iptables" 61 | #define IP6TABLES "/usr/sbin/ip6tables" 62 | #define GEOIP_DB "/usr/share/GeoIP/GeoIP.dat" 63 | #define GEOIP6_DB "/usr/share/GeoIP/GeoIPv6.dat" 64 | #define GROUP_NAME "adm" 65 | 66 | enum GlobalFlg_enum { 67 | GLB_VERBOSE_FLG =1<<0, 68 | GLB_LIST_ADDR_FLG =1<<1, 69 | GLB_LIST_CNTRY_FLG =1<<2, 70 | GLB_DONT_IPTABLE_FLG =1<<3, 71 | GLB_LIST_SUMMARY_FLG =1<<4, 72 | GLB_PRINT_LOGFILE_NAMES_FLG=1<<5, 73 | GLB_DNS_LOOKUP_FLG =1<<6, 74 | GLB_DNS_FILTER_BAD_FLG =1<<7, 75 | GLB_FLUSH_CACHE_FLG =1<<8, 76 | GLB_CMDLINE_ADDR_FLG =1<<9, 77 | GLB_LONG_LISTING_MASK = GLB_LIST_CNTRY_FLG|GLB_LIST_ADDR_FLG 78 | }; 79 | 80 | enum BlockedFlg_enum { 81 | BLOCKED_FLG =1<<0, 82 | WOULD_BLOCK_FLG =1<<1, 83 | UNJUST_BLOCK_FLG =1<<2, 84 | WHITELIST_FLG =1<<3 85 | }; 86 | 87 | /* Singleton static object with global visibility */ 88 | extern struct Global { 89 | 90 | enum GlobalFlg_enum flags; 91 | 92 | MAP logType_map; 93 | 94 | struct { 95 | char *dir; 96 | mode_t dir_mode, 97 | file_mode; 98 | } cache; 99 | 100 | struct { 101 | char *dir; 102 | mode_t dir_mode, 103 | file_mode; 104 | } lock; 105 | 106 | /* This should be set to adm */ 107 | gid_t gid; 108 | 109 | struct { 110 | FILE *fh; 111 | MAP AddrRPT_map; 112 | } rpt; 113 | 114 | struct { 115 | int major, 116 | minor, 117 | patch; 118 | } version; 119 | 120 | struct { 121 | const struct bitTuple *flags; 122 | } bitTuples; 123 | 124 | struct { 125 | time_t time_t; 126 | struct tm tm; 127 | } begin; 128 | 129 | } G; 130 | 131 | 132 | #endif 133 | 134 | -------------------------------------------------------------------------------- /logFile.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef LOGFILE_H 20 | #define LOGFILE_H 21 | 22 | #define _GNU_SOURCE 23 | #include 24 | 25 | #include "logType.h" 26 | #include "map.h" 27 | 28 | /* One of these for each log file which is scanned. */ 29 | typedef struct _LOGFILE { 30 | int flags; 31 | char *logFname; 32 | struct { 33 | MAP offEntry_map, 34 | obsvTpl_map; 35 | } addr; /* addr denotes the map keys */ 36 | unsigned nOffenses; 37 | } LOGFILE; 38 | 39 | #define LOGFILE_logFname(self) \ 40 | (const char*)(self)->logFname 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | #define LOGFILE_cache_create(s, cacheFname, logFname) \ 47 | ((s)=(LOGFILE_cache_constructor((s)=malloc(sizeof(LOGFILE)), cacheFname, logFname) ? (s) : ( s ? realloc(LOGFILE_destructor(s),0) : 0 ))) 48 | LOGFILE* 49 | LOGFILE_cache_constructor( 50 | LOGFILE *self, 51 | const char *cacheFname, 52 | const char *logFname 53 | ); 54 | /****************************************************************** 55 | * Initialize an instance of a LOGFILE class. 56 | */ 57 | 58 | #define LOGFILE_log_create(s, h_protoType, logFname) \ 59 | ((s)=(LOGFILE_log_constructor((s)=malloc(sizeof(LOGFILE)), h_protoType, logFname) ? (s) : ( s ? realloc(LOGFILE_destructor(s),0) : 0 ))) 60 | LOGFILE* 61 | LOGFILE_log_constructor( 62 | LOGFILE *self, 63 | const struct logProtoType *h_protoType, 64 | const char *logFname 65 | ); 66 | /****************************************************************** 67 | * Initialize an instance of a LOGFILE class. 68 | */ 69 | 70 | #define LOGFILE_destroy(s) \ 71 | {if(LOGFILE_destructor(s)) {free(s);(s)=0;}} 72 | LOGFILE* 73 | LOGFILE_destructor(LOGFILE *self); 74 | /****************************************************************** 75 | * Free resources associated with a LOGFILE object. 76 | */ 77 | 78 | #if 0 79 | void 80 | LOGFILE_set_logFname(LOGFILE *self, const char *path); 81 | /****************************************************************** 82 | * Set the log file name by making a copy of the path. 83 | */ 84 | #endif 85 | 86 | int 87 | LOGFILE_writeCache(LOGFILE *self, const char *fname); 88 | /****************************************************************** 89 | * Create a cache file and dump contents of this object. 90 | */ 91 | 92 | int 93 | LOGFILE_print(LOGFILE *self, FILE *fh); 94 | /******************************************************** 95 | * Print a human readable representation of *self. 96 | */ 97 | 98 | int 99 | LOGFILE_map_addr(LOGFILE *self, MAP *h_rtnMap); 100 | /******************************************************** 101 | * Create a map of OFFENTRY objects with composite 102 | * counts by address. 103 | */ 104 | 105 | int 106 | LOGFILE_offenseCount(LOGFILE *self, unsigned *h_sum); 107 | /******************************************************** 108 | * Get a count of all offenses for this file. 109 | */ 110 | 111 | int 112 | LOGFILE_addressCount(LOGFILE *self, unsigned *h_sum); 113 | /******************************************************** 114 | * Get a count of all unique addresses for this file. 115 | */ 116 | 117 | #ifdef __cplusplus 118 | } 119 | #endif 120 | 121 | #endif /* LOGFILE_H */ 122 | -------------------------------------------------------------------------------- /ban2fail.cfg: -------------------------------------------------------------------------------- 1 | # By default, no number of offenses are tolerated 2 | 3 | # Whitelist ourself 4 | MAX_OFFENSES -1 { 5 | # Put your server's IP addresses here 6 | # IP= 1.2.3.4 7 | IP= 127.0.0.1 8 | # IP= dead:beef::20::32a 9 | IP= ::1 10 | } 11 | 12 | # Allegedly legit servers 13 | MAX_OFFENSES 50 { 14 | 15 | # Google Ireland 16 | IP= 2a00:1450:4864:20::32a 17 | IP= 2a00:1450:4864:20::336 18 | 19 | # Google EU 20 | # Attempted to break in 21 | # IP= 35.205.240.168 22 | 23 | # Google US 24 | IP= 09.85.216.42 25 | # Attempted to break in 26 | # IP= 130.211.246.128 27 | IP= 209.85.166.194 28 | IP= 209.85.166.195 29 | IP= 209.85.208.67 30 | IP= 209.85.214.194 31 | IP= 209.85.215.173 32 | IP= 209.85.215.175 33 | IP= 209.85.215.193 34 | IP= 209.85.216.42 35 | IP= 2607:f8b0:4864:20::1034 36 | IP= 2607:f8b0:4864:20::a46 37 | 38 | # Yahoo 39 | IP= 106.10.244.139 40 | 41 | # Outlook 42 | IP= 40.92.4.30 43 | IP= 40.107.73.61 44 | IP= 40.107.74.48 45 | IP= 40.107.74.72 46 | IP= 40.107.76.74 47 | IP= 40.107.79.52 48 | IP= 40.107.79.59 49 | IP= 40.107.80.40 50 | IP= 40.107.80.53 51 | IP= 40.107.80.78 52 | IP= 40.107.82.75 53 | IP= 52.101.129.30 54 | IP= 52.101.132.108 55 | IP= 52.101.136.79 56 | IP= 52.101.140.230 57 | } 58 | 59 | # "trusted" addresses 60 | MAX_OFFENSES 200 { 61 | 62 | # me from home 63 | # IP= 1.2.3.4/20 64 | 65 | # Customer 66 | # IP= 5.6.7.8/24 67 | } 68 | 69 | LOGTYPE auth { 70 | 71 | # Where to find the log files 72 | DIR= /var/log 73 | PREFIX= auth.log 74 | 75 | # How to read the timestamp 76 | TIMESTAMP auth_ts { 77 | # isolates the timestamp from a line matched by a TARGET 78 | REGEX= ^(.*) srv 79 | # Passed to strptime() to intrepret the timestamp string 80 | STRPTIME= %b %d %T 81 | # These stamps do not include the year, so it is implied. 82 | FLAGS= GUESS_YEAR 83 | } 84 | 85 | TARGET imap { 86 | # Pattern to search for, isolates the IP address 87 | REGEX= imapd.*Login failed.*\[([0-9.a-f:]+)\]$ 88 | # Assign this as the severity of the offense. 89 | SEVERITY= 3 90 | } 91 | 92 | TARGET ssh { 93 | SEVERITY= 4 94 | REGEX= sshd.*Failed password.*from ([0-9.a-f:]+) port [0-9]+ ssh2$ 95 | REGEX= sshd.*Invalid user.*from ([0-9.a-f:]+) port 96 | } 97 | 98 | TARGET negotiate_fail { 99 | SEVERITY= 2 100 | REGEX= Unable to negotiate with ([0-9.a-f:]+) port 101 | } 102 | 103 | TARGET dovecot { 104 | SEVERITY= 3 105 | REGEX= dovecot.*authentication failure.*rhost=([0-9.a-f:]+) 106 | } 107 | 108 | } 109 | 110 | LOGTYPE exim4 { 111 | 112 | DIR= /var/log/exim4 113 | PREFIX= mainlog 114 | 115 | TIMESTAMP exim4_ts { 116 | REGEX= ^([-0-9]+ [0-9:]+) 117 | STRPTIME= %F %T 118 | } 119 | 120 | TARGET smtp_auth { 121 | SEVERITY= 3 122 | REGEX= [[:alnum:]_]+ authenticator failed for .*\[([0-9.a-f:]+)\] 123 | REGEX= \[([0-9.a-f:]+)\] [[:alnum:]_]+ authentication mechanism not supported 124 | } # smtp_auth 125 | 126 | TARGET smtp_send { 127 | SEVERITY= 9 128 | REGEX= \[([0-9.a-f:]+)\] P=.*A=[[:alnum:]_]+_server: 129 | } # smtp_send 130 | 131 | 132 | TARGET spam { 133 | REGEX= H=.* \[([0-9.a-f:]+)\].*rejected RCPT.*Unrouteable address 134 | 135 | REGEX= : ([0-9.a-f:]+) is listed at zen.spamhaus.org 136 | 137 | REGEX= H=.* \[([0-9.a-f:]+)\].*rejected RCPT.*SPF check failed 138 | 139 | REGEX= \[([0-9.a-f:]+)\]: SMTP error.*: 451 relay 140 | 141 | REGEX= \[([0-9.a-f:]+)\] F=.*rejected RCPT.*Sender verify failed 142 | } # spam 143 | 144 | TARGET brain_damage { 145 | REGEX= H=.* \[([0-9.a-f:]+)\].*rejected after DATA: maximum allowed line length 146 | 147 | REGEX= SMTP protocol synchronization error.* rejected.* H=\[([0-9.a-f:]+)\] 148 | } # brain_damage 149 | } 150 | 151 | LOGTYPE apache2 { 152 | 153 | DIR= /var/log/apache2 154 | PREFIX= access.log 155 | 156 | TIMESTAMP apache2_ts { 157 | REGEX= ^[0-9.a-f:]+ - - \[([^ ]+) 158 | STRPTIME= %d/%b/%Y:%T 159 | } 160 | 161 | TARGET worm { 162 | REGEX= ^([0-9.a-f:]+) .*(thinkphp|elrekt\.php|download\.php|ysyqq\.php|Login\.php|phpmyadmin|cfgss\.php|wallet\.dat|y000000000000\.cfg) 163 | } 164 | 165 | } 166 | 167 | LOGTYPE openvpn { 168 | DIR= /var/log 169 | PREFIX= openvpn.log 170 | 171 | TIMESTAMP openvpn_ts { 172 | REGEX= ^(.*) client/ 173 | STRPTIME= %a %b %d %T %Y 174 | } 175 | 176 | TARGET client { 177 | SEVERITY= 9 178 | #Tue Dec 3 10:52:22 2019 client/184.185.212.118:38752 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, 2048 bit RSA 179 | # REGEX= client/([0-9.a-f:]+):[0-9]+ Control Channel: 180 | } 181 | } 182 | 183 | -------------------------------------------------------------------------------- /target.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | 20 | #define _GNU_SOURCE 21 | #include 22 | #include 23 | #include 24 | 25 | #include "target.h" 26 | #include "util.h" 27 | 28 | int 29 | Target_init(Target *self, CFGMAP *h_map, const char *pfix) 30 | /******************************************************** 31 | * Prepare for use from config map 32 | */ 33 | { 34 | int rtn= -1; 35 | memset(self, 0, sizeof(*self)); 36 | 37 | self->flags |= TARGET_INIT_FLG; 38 | 39 | unsigned arr_sz= CFGMAP_numTuples(h_map); 40 | struct CFGMAP_tuple rtn_arr[arr_sz]; 41 | 42 | size_t len= strlen(pfix)+1024; 43 | char symBuf[len]; 44 | 45 | { /*--- Check for "SEVERITY" symbol ---*/ 46 | snprintf(symBuf, len, "%s\\SEVERITY", pfix); 47 | 48 | if(CFGMAP_query_last_uint(h_map, &self->severity, 0, symBuf)) { 49 | eprintf("ERROR: cannot interpret \"SEVERITY\" entry for REGEX %s", pfix); 50 | goto abort; 51 | } 52 | #ifdef qqDEBUG 53 | eprintf("%s = %u", symBuf, self->severity); 54 | #endif 55 | } 56 | 57 | { /*--- Get all REGEX entries ---*/ 58 | snprintf(symBuf, len, "%s\\REGEX", pfix); 59 | self->nRx= CFGMAP_find_tuples(h_map, rtn_arr, symBuf); 60 | 61 | self->rxArr= calloc(self->nRx, sizeof(struct TargetRx)); 62 | assert(self->rxArr); 63 | 64 | for(unsigned i= 0; i < self->nRx; ++i) { 65 | 66 | const struct CFGMAP_tuple *tpl= rtn_arr + i; 67 | struct TargetRx *rx= self->rxArr + i; 68 | 69 | /* Compile regular expression */ 70 | rx->pattern= tpl->value; 71 | if(regex_compile(&rx->re, rx->pattern, REG_EXTENDED)) { 72 | eprintf("ERROR: regex_compile(\"%s\") failed.", rx->pattern); 73 | goto abort; 74 | } 75 | } 76 | } 77 | 78 | rtn= 0; 79 | abort: 80 | return rtn; 81 | } 82 | 83 | void* 84 | Target_destructor(Target *self) 85 | /******************************************************** 86 | * Free resources. 87 | */ 88 | { 89 | if(self->nRx && self->rxArr) { 90 | for(unsigned i= 0; i < self->nRx; ++i) { 91 | struct TargetRx *rx= self->rxArr + i; 92 | regfree(&rx->re); 93 | } 94 | free(self->rxArr); 95 | } 96 | 97 | return self; 98 | } 99 | 100 | int 101 | Target_scan(const Target *self, char *rsltBuf, unsigned buf_sz, const char *str) 102 | /******************************************************** 103 | * Scan a string to obtain the address. 104 | */ 105 | { 106 | int rtn= EOF; 107 | 108 | /* Exit on first match */ 109 | for(unsigned i= 0; i < self->nRx; ++i) { 110 | 111 | const struct TargetRx *rx= self->rxArr+i; 112 | 113 | regmatch_t matchArr[2]; 114 | if(0 != regexec(&rx->re, str, 2, matchArr, 0) || -1 == matchArr[1].rm_so) 115 | continue; 116 | 117 | unsigned len= matchArr[1].rm_eo - matchArr[1].rm_so; 118 | 119 | strncpy(rsltBuf, str+matchArr[1].rm_so, buf_sz-1); 120 | rsltBuf[MIN(len, buf_sz-1)]= '\0'; 121 | rtn= 0; 122 | break; 123 | } 124 | 125 | abort: 126 | return rtn; 127 | } 128 | 129 | int 130 | Target_MD5_update(const Target *self, MD5_CTX *ctx) 131 | /******************************************************** 132 | * For computing MD5 checksum of cumulative patterns. 133 | */ 134 | { 135 | MD5_Update(ctx, &self->severity, sizeof(self->severity)); 136 | 137 | for(unsigned i= 0; i < self->nRx; ++i) { 138 | const struct TargetRx *rx= self->rxArr+i; 139 | MD5_Update(ctx, rx->pattern, strlen(rx->pattern)); 140 | } 141 | return 0; 142 | } 143 | -------------------------------------------------------------------------------- /addrRpt.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #define _GNU_SOURCE 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "addrRpt.h" 26 | #include "ban2fail.h" 27 | #include "ez_libc.h" 28 | #include "logFile.h" 29 | #include "logType.h" 30 | #include "util.h" 31 | 32 | /*==================================================================*/ 33 | /*================= Match ==========================================*/ 34 | /*==================================================================*/ 35 | /* One of these object for each LOGFILE 36 | * which contains matches. 37 | */ 38 | typedef struct _Match { 39 | LOGFILE *lf; 40 | char *line; 41 | } Match; 42 | 43 | #define Match_create(p, logfile, line) \ 44 | ((p)=(Match_constructor((p)=malloc(sizeof(Match)), logfile, line) ? (p) : ( p ? realloc(Match_destructor(p),0) : 0 ))) 45 | static Match* 46 | Match_constructor(Match *self, LOGFILE *lf, const char *line) 47 | /******************************************************** 48 | * Prepare for use. 49 | */ 50 | { 51 | memset(self, 0, sizeof(*self)); 52 | self->lf= lf; 53 | self->line= strdup(line); 54 | return self; 55 | } 56 | 57 | #define Match_destroy(s) \ 58 | {if(Match_destructor(s)) {free(s); (s)=0;}} 59 | static void* 60 | Match_destructor(Match *self) 61 | /******************************************************** 62 | * Free resources. 63 | */ 64 | { 65 | if(self->line) 66 | free(self->line); 67 | return self; 68 | } 69 | 70 | /*==================================================================*/ 71 | /*================= AddrRPT ========================================*/ 72 | /*==================================================================*/ 73 | AddrRPT* 74 | AddrRPT_addr_constructor(AddrRPT *self, const char *addr) 75 | /******************************************************** 76 | * Prepare for use from an address on the command line 77 | */ 78 | { 79 | memset(self, 0, sizeof(*self)); 80 | 81 | strncpy(self->addr, addr, sizeof(self->addr)-1); 82 | PTRVEC_constructor(&self->match_vec, 100); 83 | 84 | /* Stamp with serial number so reporting at the end can be 85 | * in the order addresses were supplied on the command 86 | * line. 87 | */ 88 | static unsigned count; 89 | self->serial= ++count; 90 | 91 | return self; 92 | } 93 | 94 | void* 95 | AddrRPT_destructor(AddrRPT *self) 96 | /******************************************************** 97 | * Free resources. 98 | */ 99 | { 100 | Match *m; 101 | while((m= PTRVEC_remHead(&self->match_vec))) 102 | Match_destroy(m); 103 | 104 | PTRVEC_destructor(&self->match_vec); 105 | return self; 106 | } 107 | 108 | int 109 | AddrRPT_addLine(AddrRPT *self, LOGFILE *lf, const char *line) 110 | /******************************************************** 111 | * Add a matching line to this object. 112 | */ 113 | { 114 | Match *m; 115 | Match_create(m, lf, line); 116 | assert(m); 117 | PTRVEC_addTail(&self->match_vec, m); 118 | return 0; 119 | } 120 | 121 | int 122 | AddrRPT_print(AddrRPT *self, FILE *fh) 123 | /******************************************************** 124 | * Print a human readable representation of *self. 125 | */ 126 | { 127 | Match *m; 128 | unsigned i; 129 | LOGFILE *lf= NULL; 130 | ez_fprintf(fh, "====== Report for %s ======\r\n", self->addr); 131 | 132 | PTRVEC_loopFwd(&self->match_vec, i, m) { 133 | 134 | if(lf != m->lf) { 135 | ez_fprintf(fh, "------- %s -------------\r\n", LOGFILE_logFname(m->lf)); 136 | lf= m->lf; 137 | } 138 | ez_fprintf(fh, "%s\r\n", m->line); 139 | } 140 | 141 | return 0; 142 | } 143 | 144 | -------------------------------------------------------------------------------- /ez_libdb.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #define _GNU_SOURCE 20 | #include 21 | 22 | #include "util.h" 23 | #include "ez_libdb.h" 24 | 25 | /***************************************************/ 26 | ez_proto (int, db_create, 27 | DB **dbp, 28 | DB_ENV *dbenv, 29 | u_int32_t flags) 30 | { 31 | int rtn= db_create (dbp, dbenv, flags); 32 | 33 | if(!rtn) return 0; 34 | 35 | /* _sys_eprintf() will pass errno to db_sterror */ 36 | errno= rtn; 37 | _sys_eprintf((const char*(*)(int))db_strerror 38 | #ifdef DEBUG 39 | , fileName, lineNo, funcName 40 | #endif 41 | , "db_create() failed"); 42 | abort(); 43 | } 44 | 45 | /***************************************************/ 46 | ez_proto (int, db_open, 47 | DB *db, 48 | DB_TXN *txnid, 49 | const char *file, 50 | const char *database, 51 | DBTYPE type, 52 | u_int32_t flags, 53 | int mode) 54 | { 55 | int rtn= db->open(db, txnid, file, database, type, flags, mode); 56 | 57 | if(!rtn) return 0; 58 | 59 | /* _sys_eprintf() will pass errno to db_sterror */ 60 | errno= rtn; 61 | _sys_eprintf((const char*(*)(int))db_strerror 62 | #ifdef DEBUG 63 | , fileName, lineNo, funcName 64 | #endif 65 | , "DB->open(\"%s\") failed", database); 66 | abort(); 67 | } 68 | 69 | /***************************************************/ 70 | ez_proto (int, db_put, 71 | DB *db, 72 | DB_TXN *txnid, 73 | DBT *key, 74 | DBT *data, 75 | u_int32_t flags) 76 | { 77 | int rtn= db->put(db, txnid, key, data, flags); 78 | 79 | if(!rtn) return 0; 80 | 81 | /* _sys_eprintf() will pass errno to db_sterror */ 82 | errno= rtn; 83 | _sys_eprintf((const char*(*)(int))db_strerror 84 | #ifdef DEBUG 85 | , fileName, lineNo, funcName 86 | #endif 87 | , "DB->put() failed"); 88 | abort(); 89 | } 90 | 91 | /***************************************************/ 92 | ez_proto (int, db_get, 93 | DB *db, 94 | DB_TXN *txnid, 95 | DBT *key, 96 | DBT *data, 97 | u_int32_t flags) 98 | { 99 | int rtn= db->get(db, txnid, key, data, flags); 100 | 101 | switch(rtn) { 102 | case 0: 103 | case DB_NOTFOUND: 104 | return rtn; 105 | } 106 | 107 | /* _sys_eprintf() will pass errno to db_sterror */ 108 | errno= rtn; 109 | _sys_eprintf((const char*(*)(int))db_strerror 110 | #ifdef DEBUG 111 | , fileName, lineNo, funcName 112 | #endif 113 | , "DB->get() failed"); 114 | abort(); 115 | } 116 | 117 | /***************************************************/ 118 | ez_proto (int, db_del, 119 | DB *db, 120 | DB_TXN *txnid, 121 | DBT *key, 122 | u_int32_t flags) 123 | { 124 | int rtn= db->del(db, txnid, key, flags); 125 | 126 | if(!rtn) return 0; 127 | 128 | /* _sys_eprintf() will pass errno to db_sterror */ 129 | errno= rtn; 130 | _sys_eprintf((const char*(*)(int))db_strerror 131 | #ifdef DEBUG 132 | , fileName, lineNo, funcName 133 | #endif 134 | , "DB->del() failed"); 135 | abort(); 136 | } 137 | 138 | /***************************************************/ 139 | ez_proto (int, db_close, DB *db, u_int32_t flags) 140 | { 141 | int rtn= db->close(db, flags); 142 | 143 | if(!rtn) return 0; 144 | 145 | /* _sys_eprintf() will pass errno to db_sterror */ 146 | errno= rtn; 147 | _sys_eprintf((const char*(*)(int))db_strerror 148 | #ifdef DEBUG 149 | , fileName, lineNo, funcName 150 | #endif 151 | , "DB->close() failed"); 152 | abort(); 153 | } 154 | 155 | /***************************************************/ 156 | ez_proto (int, db_fd, DB *db, int *fdp) 157 | { 158 | int rtn= db->fd(db, fdp); 159 | 160 | if(!rtn) return 0; 161 | 162 | /* _sys_eprintf() will pass errno to db_sterror */ 163 | errno= rtn; 164 | _sys_eprintf((const char*(*)(int))db_strerror 165 | #ifdef DEBUG 166 | , fileName, lineNo, funcName 167 | #endif 168 | , "DB->fd() failed"); 169 | abort(); 170 | } 171 | -------------------------------------------------------------------------------- /msgqueue.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2008 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the GNU General Public License * 16 | * along with this program; if not, write to the * 17 | * Free Software Foundation, Inc., * 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 19 | ***************************************************************************/ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "ez_libpthread.h" 27 | #include "msgqueue.h" 28 | #include "util.h" 29 | 30 | 31 | MSGQUEUE * 32 | MSGQUEUE_constructor (MSGQUEUE * self, size_t msgSize, unsigned int queueLen) 33 | { 34 | if (!self) 35 | return NULL; 36 | 37 | pthread_mutex_init (&self->mtx, NULL); 38 | 39 | /* Allocate the memory in which to store messages */ 40 | if (!(self->buff_ptr = (char *) malloc (msgSize * queueLen))) 41 | return NULL; 42 | 43 | 44 | /* Initialize the header segment */ 45 | self->numItems = 0; 46 | self->head = 0; 47 | self->tail = 0; 48 | self->msgSize = msgSize; 49 | self->maxItems = queueLen; 50 | 51 | return self; 52 | } 53 | 54 | void* 55 | MSGQUEUE_destructor (MSGQUEUE * self) 56 | { 57 | pthread_mutex_destroy (&self->mtx); 58 | free (self->buff_ptr); 59 | return self; 60 | } 61 | 62 | int 63 | MSGQUEUE_submitMsg (MSGQUEUE * self, const void *msgBuf) 64 | /******************************************************************* 65 | * Submit a message to the message queue. 66 | */ 67 | { 68 | int rtn = 0; 69 | 70 | ez_pthread_mutex_lock (&self->mtx); 71 | 72 | if (self->numItems == self->maxItems) 73 | { 74 | #ifdef DEBUG 75 | eprintf("WARNING: %p queue full.", self); 76 | #endif 77 | rtn = EOF; 78 | goto abort; 79 | } 80 | 81 | /* If this is not the first item to be added */ 82 | if (self->numItems) 83 | self->tail = (self->tail + 1) % self->maxItems; 84 | 85 | memcpy (self->buff_ptr + self->tail * self->msgSize, msgBuf, self->msgSize); 86 | 87 | ++self->numItems; 88 | 89 | abort: 90 | ez_pthread_mutex_unlock (&self->mtx); 91 | return rtn; 92 | } 93 | 94 | int 95 | MSGQUEUE_extractMsg (MSGQUEUE * self, void *msgBuf) 96 | /***************************************************************************** 97 | * Extract a message from the message queue. Returns EOF when queue is empty. 98 | */ 99 | { 100 | int rtn = 0; 101 | 102 | ez_pthread_mutex_lock (&self->mtx); 103 | if (!self->numItems) 104 | { 105 | rtn = EOF; 106 | goto abort; 107 | } 108 | 109 | self->numItems--; 110 | memcpy (msgBuf, self->buff_ptr + self->head * self->msgSize, self->msgSize); 111 | 112 | if (self->numItems) 113 | self->head = (self->head + 1) % self->maxItems; 114 | 115 | abort: 116 | ez_pthread_mutex_unlock (&self->mtx); 117 | return rtn; 118 | } 119 | 120 | 121 | int 122 | MSGQUEUE_checkQueue (MSGQUEUE * self, 123 | int (*check) (void *data_ptr, void *arg), void *arg) 124 | /***************************************************************************** 125 | * Runs through the message queuue calling check() until it returns non-zero, 126 | * or the queue is fully traversed. 127 | * Return: 0 -> check() always returned zero, or queue was empty. 128 | * otherwise, return value of check(). 129 | */ 130 | { 131 | int rtn = 0; 132 | unsigned int i; 133 | void *ptr; 134 | 135 | ez_pthread_mutex_lock (&self->mtx); 136 | 137 | if (!self->numItems) 138 | goto abort; 139 | 140 | for (i = 0, ptr = self->buff_ptr + self->head * self->msgSize; 141 | i < self->numItems; 142 | ++i, ptr = 143 | self->buff_ptr + ((self->head + i) % self->maxItems) * self->msgSize) 144 | { 145 | if ((rtn = (*check) (ptr, arg))) 146 | break; 147 | } 148 | 149 | abort: 150 | ez_pthread_mutex_unlock (&self->mtx); 151 | return rtn; 152 | } 153 | 154 | /************************************************************/ 155 | int _ez_MSGQUEUE_submitMsg( 156 | const char *fileName, 157 | int lineNo, 158 | const char *funcName, 159 | MSGQUEUE *self, 160 | const void *msgBuf 161 | ) 162 | { 163 | int rtn= MSGQUEUE_submitMsg (self, msgBuf); 164 | 165 | if(!rtn) return 0; 166 | 167 | _eprintf(fileName, lineNo, funcName, "MSGQUEUE_submitMsg() failed"); 168 | abort(); 169 | } 170 | -------------------------------------------------------------------------------- /ez.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * In an effort to make C programming both easier and more secure, I present 3 | * the EZ method. 4 | * 5 | * Reasoning for this is simple; Many function calls can fail for a variety of 6 | * reasons, some or even most of which are obscure. However, it is both 7 | * insecure and counterproductive not to check for said failures. Unfortunately 8 | * coding proper checks and/or recovery from failures will involve (often 9 | * complex) logic constructs, and detracts from understanding the primary logic 10 | * of your source code. 11 | * 12 | * Sometimes your app needs to recover, and so you must supply this code, but 13 | * more often than not a "boilplate" approach is sufficient. The EZ method is a 14 | * consistent convention to supply centralized and reusable "boilerplate" error 15 | * handling on an _optional_ basis, both for existing library functions and 16 | * your own. 17 | * 18 | * Modern programming languages address this problem by throwing "exceptions", 19 | * which by default result in your program getting terminated. To avoid 20 | * termination you must write code to "catch" such exceptions, but this code 21 | * exists separated in source code from the function call, and tends to be both 22 | * confusing to read and hideous to look at. If you thought "goto" statements 23 | * were in poor taste, then this will make you vomit. 24 | * 25 | * Enter the EZ method; from a practical coding standpoint you merely prepend 26 | * "ez_" to any function call for which you desire default error handling. When 27 | * an error occurs a very helpful error message is printed (in DEBUG mode this 28 | * includes the source code location from which the function was called), and 29 | * your program is terminated. If your app needs to recover from such an error, 30 | * simply erase the "ez_" prefix from the function call and supply the recovery 31 | * code, where God intended it to be - right where you made the function call! 32 | * 33 | * In effect the EZ method provides the utility of throwing exceptions, but 34 | * without the catch - Woohoo! 35 | *****************************************************************************/ 36 | 37 | #ifndef EZ_H 38 | #define EZ_H 39 | 40 | 41 | /***************************************************************************** 42 | * These macros ease the drudgery of writing prototypes for the _ez_XXX() 43 | * wrappers of functions, and reduce the liklihood of bugs due to typing 44 | * errors. 45 | * 46 | * The elipses is for your function's argument list. 47 | *****************************************************************************/ 48 | 49 | #ifdef DEBUG 50 | 51 | #define ez_proto(rtn, funcname, ...) \ 52 | rtn _ez_##funcname( \ 53 | const char *fileName, \ 54 | int lineNo, \ 55 | const char *funcName, \ 56 | ##__VA_ARGS__ \ 57 | ) 58 | 59 | #define ez_hdr_proto(rtn, funcname, ...) \ 60 | ez_proto(rtn, funcname, ##__VA_ARGS__); \ 61 | rtn funcname(__VA_ARGS__) 62 | 63 | #else 64 | 65 | #define ez_proto(rtn, funcname, ...) \ 66 | rtn _ez_##funcname(__VA_ARGS__) 67 | 68 | #define ez_hdr_proto(rtn, funcname, ...) \ 69 | ez_proto(rtn, funcname, ##__VA_ARGS__); \ 70 | rtn funcname(__VA_ARGS__) 71 | 72 | #endif 73 | 74 | /***************************************************************************** 75 | * For example, if you have the following function prototype: 76 | * 77 | * int myfunc (struct foo *f, double bar) 78 | * 79 | * In the header file where the function prototype goes, 80 | * you will need this: 81 | * 82 | * ez_hdr_proto (int, myfunc, struct foo *f, double bar); 83 | * 84 | * #ifdef DEBUG 85 | * # define ez_myfunc(...) \ 86 | * _ez_myfunc(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 87 | * #else 88 | * # define ez_myfunc(...) \ 89 | * _ez_myfunc(__VA_ARGS__) 90 | * #endif 91 | * 92 | * This will expand to the standard function prototype as listed above, as well 93 | * as the _ez_myfunc() prototype correct for either DEBUG version or production 94 | * version, depending on whether or not DEBUG is #define'd. Also, there is now 95 | * a macro ez_myfunc() which will expand to the correct _ez_myfunc() 96 | * function call. 97 | * 98 | * In the implmentation (*.c) file, you will need to supply code for 99 | * _ez_myfunc(), which looks like so: 100 | * 101 | * ez_proto(int, myfunc, struct foo *f, double bar) 102 | * { 103 | * // implementation goes here 104 | * } 105 | * 106 | * Notice that the prototype section is is the same as what you placed in the 107 | * corresponding header file, minus "_hdr" in the ez_hdr_proto() macro. 108 | * 109 | * For the case where you are supplying only the ez_XXX() version of an 110 | * existing function found in some library 'liba2z', you can place the 111 | * following in your own header file, "ez_liba2z.h": 112 | * 113 | * ez_proto(struct rtnType*, liba2z_funcname, struct foo *f, double bar); 114 | * 115 | * Everything else works similar to the previous examples. 116 | * Now you can use the EZ error handling like so: 117 | * 118 | * #include "ez_liba2z.h" 119 | * int main(int argc, char **argv) 120 | * { 121 | * struct foo Foo; 122 | * double bar; 123 | * struct rtnType *rtn= ez_liba2z_funcname(&Foo, bar); 124 | * } 125 | * 126 | *****************************************************************************/ 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /timestamp.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | 20 | #define _GNU_SOURCE 21 | #include "ez_libc.h" 22 | #include "timestamp.h" 23 | #include "util.h" 24 | 25 | 26 | enum Flags { 27 | GUESS_YR_FLG= 1<<0 28 | }; 29 | 30 | const static struct bitTuple FlagsBitTupleArr[]= { 31 | {.name= "GUESS_YEAR", .bit= GUESS_YR_FLG}, 32 | {/* Terminating member */} 33 | }; 34 | 35 | int 36 | TS_init(TS *self, CFGMAP *h_map, const char *pfix) 37 | /******************************************************** 38 | * Initialize timestamp from config map. 39 | */ 40 | { 41 | int rtn= -1; 42 | memset(self, 0, sizeof(*self)); 43 | 44 | size_t len= strlen(pfix)+1024; 45 | char symBuf[len]; 46 | 47 | { /*--- Check for "REGEX" symbol ---*/ 48 | snprintf(symBuf, len, "%s\\REGEX", pfix); 49 | /* CFGMAP is left in place, so we don't need to strdup() */ 50 | self->pattern= CFGMAP_find_last_value(h_map, symBuf); 51 | 52 | if(!self->pattern) { 53 | eprintf("ERROR: cannot find \"REGEX\" entry for ENTRY_TIMESTAMP %s", pfix); 54 | goto abort; 55 | } 56 | 57 | if(regex_compile(&self->re, self->pattern, REG_EXTENDED)) { 58 | eprintf("ERROR: regex_compile(\"%s\") failed.", self->pattern); 59 | goto abort; 60 | } 61 | } 62 | 63 | { /*--- Check for "STRPTIME" symbol ---*/ 64 | snprintf(symBuf, len, "%s\\STRPTIME", pfix); 65 | /* CFGMAP is left in place, so we don't need to strdup() */ 66 | self->strptime_fmt= CFGMAP_find_last_value(h_map, symBuf); 67 | 68 | if(!self->strptime_fmt) { 69 | eprintf("ERROR: cannot find \"STRPTIME\" entry for ENTRY_TIMESTAMP %s", pfix); 70 | goto abort; 71 | } 72 | } 73 | 74 | { /*--- Check for "FLAGS" symbol ---*/ 75 | const char *flagStr; 76 | snprintf(symBuf, len, "%s\\FLAGS", pfix); 77 | 78 | flagStr= CFGMAP_find_last_value(h_map, symBuf); 79 | /* This is optional */ 80 | if(flagStr) { 81 | int rc= str2bits(&self->flags, flagStr, FlagsBitTupleArr); 82 | if(rc) { 83 | eprintf("ERROR: cannot interpret \"FLAGS\" entry for ENTRY_TIMESTAMP %s", pfix); 84 | goto abort; 85 | } 86 | } 87 | } 88 | 89 | rtn= 0; 90 | abort: 91 | return rtn; 92 | } 93 | 94 | void* 95 | TS_destructor(TS *self) 96 | /******************************************************** 97 | * Free resources. 98 | */ 99 | { 100 | if(self->pattern) 101 | regfree(&self->re); 102 | return self; 103 | } 104 | 105 | int 106 | TS_scan(const TS *self, time_t *rslt, const char *str, const struct tm *pTmRef) 107 | /******************************************************** 108 | * Scan a string to obtain the timestamp. 109 | */ 110 | { 111 | int rtn= -1; 112 | 113 | /* If there is no match, continue looking */ 114 | regmatch_t matchArr[2]; 115 | if(0 != regexec(&self->re, str, 2, matchArr, 0) || -1 == matchArr[1].rm_so) { 116 | eprintf("ERROR: failed to identify date in \"%s\"", str); 117 | goto abort; 118 | } 119 | 120 | unsigned len= matchArr[1].rm_eo - matchArr[1].rm_so; 121 | static char date[128]; 122 | strncpy(date, str+matchArr[1].rm_so, sizeof(date)-1); 123 | date[MIN(len, sizeof(date)-1)]= '\0'; 124 | static struct tm tm; 125 | memset(&tm, 0, sizeof(tm)); 126 | tm.tm_isdst= -1; 127 | 128 | const char *lc= ez_strptime(date, self->strptime_fmt, &tm); 129 | 130 | /* We may have to guess the year */ 131 | if(self->flags & GUESS_YR_FLG) { 132 | 133 | tm.tm_year= pTmRef->tm_year; 134 | 135 | if(tm.tm_mon > pTmRef->tm_mon) 136 | --tm.tm_year; 137 | } 138 | 139 | *rslt= mktime(&tm); 140 | //eprintf("Date string= \"%s\", lc= \"%s\", =? \"%s\"", date, lc, ctime(rslt)); 141 | 142 | rtn= 0; 143 | abort: 144 | return rtn; 145 | } 146 | 147 | int 148 | TS_MD5_update(const TS *self, MD5_CTX *ctx) 149 | /******************************************************** 150 | * For computing MD5 checksum of config data. 151 | */ 152 | { 153 | if(self->pattern) 154 | MD5_Update(ctx, self->pattern, strlen(self->pattern)); 155 | 156 | if(self->strptime_fmt) 157 | MD5_Update(ctx, self->strptime_fmt, strlen(self->strptime_fmt)); 158 | 159 | MD5_Update(ctx, &self->flags, sizeof(self->flags)); 160 | return 0; 161 | } 162 | -------------------------------------------------------------------------------- /dynstack.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #define _GNU_SOURCE 20 | #include 21 | #include 22 | 23 | #include "dynstack.h" 24 | 25 | #define elAddress(s, ndx)\ 26 | ((s)->stk_ptr + (ndx) * (s)->elsize) 27 | 28 | 29 | DS* 30 | DS_constructor(DS *self, unsigned int elmtSize, unsigned int numElmts ) 31 | /****************************************************************** 32 | * Open a dynamic stack, and get a key with which to interact with the stack. 33 | */ 34 | { 35 | if(!self) return NULL; 36 | memset(self, 0, sizeof(*self)); 37 | 38 | if(!( self->stk_ptr = malloc( elmtSize*numElmts ) )) return NULL; 39 | 40 | self->elsize = elmtSize; 41 | self->size = numElmts; 42 | 43 | return self; 44 | } 45 | 46 | int 47 | DS_sinit(DS *self, unsigned int elmtSize, unsigned int numElmts) 48 | /**************************************************************** 49 | * Initializion for static instance of DS. Initializes once per 50 | * process, and reset() all other times. 51 | */ 52 | { 53 | int rtn= 1; 54 | if(!self->stk_ptr) { 55 | if(!DS_constructor(self, elmtSize, numElmts)) goto abort; 56 | } else { 57 | DS_reset(self); 58 | } 59 | rtn= 0; 60 | abort: 61 | return rtn; 62 | } 63 | 64 | void* 65 | DS_destructor(DS *self ) 66 | /****************************************************************** 67 | * Close the dynamic stack and free all memory. 68 | */ 69 | { 70 | if(self->stk_ptr) free( self->stk_ptr ); 71 | return self; 72 | } 73 | 74 | static void* 75 | top( DS *self ) 76 | /********************* top() *********************************** 77 | * return a pointer to the top of the stack. 78 | */ 79 | { 80 | if(!self->count) return NULL; 81 | return (void *)elAddress( self, self->count - 1); 82 | } 83 | 84 | #define copy(s, dst, src)\ 85 | memcpy(dst, src, (s)->elsize) 86 | 87 | int 88 | DS_top( DS *self, void *dest_ptr ) 89 | /******************** DS_top() ************************************ 90 | * Pop the item off the top of the stack. 91 | */ 92 | { 93 | void *src_ptr; 94 | 95 | if(!self->count) return -1; 96 | 97 | src_ptr= (void*)elAddress(self, self->count - 1); 98 | 99 | /* Get a copy of the stack item */ 100 | copy(self, dest_ptr, src_ptr); 101 | 102 | return 0; 103 | } 104 | 105 | int 106 | DS_pop( DS *self, void *dest_ptr ) 107 | /******************** DS_pop() ************************************ 108 | * Pop the item off the top of the stack. 109 | */ 110 | { 111 | 112 | /* Try to get a copy of the top stack item */ 113 | if(DS_top(self, dest_ptr)) return -1; 114 | 115 | /* decrement the stack pointer */ 116 | --self->count; 117 | 118 | return 0; 119 | } 120 | 121 | int 122 | DS_push( DS *self, const void *src_ptr ) 123 | /******************** DS_push() *********************************** 124 | * Push an item on to the dynamic stack. 125 | */ 126 | { 127 | char *dest_ptr; 128 | 129 | /* If more memory is needed, get it */ 130 | if(self->count == self->size) { 131 | unsigned new_sz= self->size*2; 132 | char *ptr; 133 | 134 | if(!(ptr = realloc( self->stk_ptr, self->elsize * new_sz ))) return -1; 135 | 136 | self->stk_ptr= ptr; 137 | self->size= new_sz; 138 | } 139 | 140 | /* Increment the stack pointer */ 141 | ++self->count; 142 | 143 | /* Get the address to the destination memory */ 144 | dest_ptr = elAddress( self, self->count - 1); 145 | 146 | /* Make a copy of this item */ 147 | copy(self, dest_ptr, src_ptr); 148 | 149 | return 0; 150 | } 151 | 152 | int 153 | DS_entry_exists(const DS *self, const void *target_ptr) 154 | /****************************************************************** 155 | * Return true if the item exists in the stack 156 | */ 157 | { 158 | unsigned i; 159 | char *p; 160 | 161 | for(i= 0; i < self->count; i++) { 162 | p= self->stk_ptr + i * self->elsize; 163 | if(!memcmp(p, target_ptr, self->elsize)) return 1; 164 | } 165 | return 0; 166 | } 167 | 168 | int 169 | DS_visitAllEntries(DS *self, int (* func)(void *item_ptr, void *data), void *data) 170 | /******************************************************************************/ 171 | { 172 | for(unsigned i= 0; i < self->count; ++i) { 173 | void *item_ptr= self->stk_ptr + i * self->elsize; 174 | int rc= (*func)(item_ptr, data); 175 | if(rc) return rc; 176 | } 177 | return 0; 178 | } 179 | 180 | -------------------------------------------------------------------------------- /msgqueue.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2008 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the GNU General Public License * 16 | * along with this program; if not, write to the * 17 | * Free Software Foundation, Inc., * 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 19 | ***************************************************************************/ 20 | #ifndef MSGQUEUE_H 21 | #define MSGQUEUE_H 22 | 23 | #include 24 | 25 | typedef struct _MSGQUEUE 26 | /******************************* 27 | * Necessary info for circular message 28 | * ring. 29 | */ 30 | { 31 | pthread_mutex_t mtx; 32 | unsigned int numItems, head, tail; 33 | unsigned int msgSize, maxItems; 34 | char *buff_ptr; 35 | } MSGQUEUE; 36 | 37 | #ifdef __cplusplus 38 | extern "C" 39 | { 40 | #endif 41 | 42 | MSGQUEUE* 43 | MSGQUEUE_constructor ( 44 | MSGQUEUE *self, 45 | size_t msgSize, 46 | unsigned int queueLen 47 | ); 48 | /***************************************************************************** 49 | * Prepare the MSGQUEUE structure for service. 50 | * 51 | * self - Address of the MSGQUEUE structure on which to operate. 52 | * msgSize - The size of messages this queue will handle. 53 | * queueLen - How many messages can be stored in this queue. 54 | * 55 | * Returns: NULL for failure, 'self' otherwise. 56 | */ 57 | 58 | 59 | #define MSGQUEUE_create(self, msgSize, queueLen)\ 60 | (MSGQUEUE_constructor((self)=malloc(sizeof(MSGQUEUE)), msgSize, queueLen) ? (self) : ( self ? realloc(MSGQUEUE_destructor(self),0): 0)) 61 | /***************************************************************************** 62 | * Allocate and prepare the MSGQUEUE structure for service. 63 | * 64 | * self - Pointer that will be set to the address of the MSGQUEUE structure. 65 | * msgSize - The size of messages this queue will handle. 66 | * queueLen - How many messages can be stored in this queue. 67 | * 68 | * Returns: NULL for failure, 'self' otherwise. 69 | */ 70 | 71 | void* 72 | MSGQUEUE_destructor (MSGQUEUE *self); 73 | /***************************************************************************** 74 | * Free resources associated with a MSGQUEUE. Note that 'self' is not free()'d. 75 | * 76 | * self - Address of the MSGQUEUE structure on which to operate. 77 | * 78 | * Returns: NULL for failure, 'self' otherwise. 79 | */ 80 | 81 | #define MSGQUEUE_destroy(s) \ 82 | {if(MSGQUEUE_destructor(s)) {free(s);}} 83 | /***************************************************************************** 84 | * Free resources associated with a MSGQUEUE, and free the structure. 85 | * 86 | * self - Address of the MSGQUEUE structure on which to operate. 87 | */ 88 | 89 | int 90 | MSGQUEUE_submitMsg ( 91 | MSGQUEUE *self, 92 | const void *msgBuf 93 | ); 94 | /******************************************************************* 95 | * Submit a message to the message queue. 96 | * 97 | * self - Address of the MSGQUEUE structure on which to operate. 98 | * msgBuf - buffer containing the message to be copied into the queue. 99 | * 100 | * Returns: 0 for success, non-zero otherwise. 101 | */ 102 | #define ez_MSGQUEUE_submitMsg(self, msgBuf) \ 103 | _ez_MSGQUEUE_submitMsg(__FILE__, __LINE__, __FUNCTION__, self, msgBuf) 104 | int _ez_MSGQUEUE_submitMsg( 105 | const char *fileName, 106 | int lineNo, 107 | const char *funcName, 108 | MSGQUEUE *self, 109 | const void *msgBuf 110 | ); 111 | 112 | #define MSGQUEUE_submitTypedMsg(self, msg) \ 113 | MSGQUEUE_submitMsg(self, &(msg)) 114 | 115 | #define ez_MSGQUEUE_submitTypedMsg(self, msg) \ 116 | ez_MSGQUEUE_submitMsg(self, &(msg)) 117 | 118 | 119 | int 120 | MSGQUEUE_extractMsg ( 121 | MSGQUEUE *self, 122 | void *msgBuf 123 | ); 124 | /***************************************************************************** 125 | * Extract a message from the message queue if possible. 126 | * 127 | * self - Address of the MSGQUEUE structure on which to operate. 128 | * msgBuf - buffer to which the message will be copied. 129 | * 130 | * Returns: 0 for success, EOF if the queue is empty. 131 | */ 132 | #define MSGQUEUE_extractTypedMsg(self, msg) \ 133 | MSGQUEUE_extractMsg(self, &(msg)) 134 | 135 | 136 | int 137 | MSGQUEUE_checkQueue ( 138 | MSGQUEUE *self, 139 | int (*check) (void *pMsg, void *pData), 140 | void *pData 141 | ); 142 | /***************************************************************************** 143 | * Runs through the message queuue calling check() until it returns non-zero, 144 | * or the queue is fully traversed. 145 | * 146 | * self - Address of the MSGQUEUE structure on which to operate. 147 | * check - Function to be called for each message in the queue. 148 | * pData - A pointer that will be passed into check() when it is called. 149 | * 150 | * Return: 0 -> check() always returned zero, or queue was empty. 151 | * otherwise, return value of check(). 152 | */ 153 | #ifdef __cplusplus 154 | } 155 | #endif 156 | 157 | #endif 158 | -------------------------------------------------------------------------------- /obsvTpl.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #define _GNU_SOURCE 20 | #include 21 | 22 | #include "ez_libdb.h" 23 | #include "ez_libc.h" 24 | #include "ez_libz.h" 25 | #include "obsvTpl.h" 26 | 27 | /* Make sure we don't have padding at the end of this struct */ 28 | #pragma pack(push,2) 29 | struct obsv { 30 | z_off_t pos; /* position in the file */ 31 | uint16_t len; /* length of string to retrieve */ 32 | }; 33 | #pragma pack(pop) 34 | 35 | ObsvTpl* 36 | ObsvTpl_constructor(ObsvTpl *self, LOGFILE *lf, const char *addr) 37 | /***************************************************************** 38 | * prepare for use. 39 | */ 40 | { 41 | memset(self, 0, sizeof(*self)); 42 | 43 | strncpy(self->addr, addr, sizeof(self->addr)-1); 44 | self->lf= lf; 45 | DS_constructor(&self->stack, sizeof(struct obsv), 10000); 46 | return self; 47 | } 48 | 49 | int 50 | ObsvTpl_sinit(ObsvTpl *self, LOGFILE *lf, const char *addr) 51 | /******************************************************** 52 | * Initialize or reset a static instance 53 | */ 54 | { 55 | if(self->lf) { 56 | memset(self->addr, 0, sizeof(self->addr)); 57 | strncpy(self->addr, addr, sizeof(self->addr)-1); 58 | self->lf= lf; 59 | DS_reset(&self->stack); 60 | } else { 61 | ObsvTpl_constructor(self, lf, addr); 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | void* 68 | ObsvTpl_destructor(ObsvTpl *self) 69 | /***************************************************************** 70 | * Free resources 71 | */ 72 | { 73 | 74 | DS_destructor(&self->stack); 75 | 76 | return self; 77 | } 78 | 79 | int 80 | ObsvTpl_addObsv(ObsvTpl *self, z_off_t pos, unsigned len) 81 | /***************************************************************** 82 | * Add an observation to this report object. 83 | */ 84 | { 85 | struct obsv obs; 86 | obs.pos= pos; 87 | obs.len= len; 88 | DS_push(&self->stack, &obs); 89 | return 0; 90 | } 91 | 92 | int 93 | ObsvTpl_db_put(ObsvTpl *self, DB *db) 94 | /***************************************************************** 95 | * Write our contents into the database. 96 | */ 97 | { 98 | int rtn= -1; 99 | 100 | DBT key= { 101 | .data= self->addr, 102 | .size= strlen(self->addr) 103 | }, 104 | data= { 105 | .data= DS_ptr(&self->stack), 106 | .size= DS_numItems(&self->stack) * sizeof(struct obsv) 107 | }; 108 | 109 | /* Write data to database */ 110 | ez_db_put(db, NULL, &key, &data, 0); 111 | 112 | rtn= 0; 113 | abort: 114 | return rtn; 115 | } 116 | 117 | int 118 | ObsvTpl_db_get(ObsvTpl *self, DB *db) 119 | /******************************************************** 120 | * Fetch our content from a database. 121 | */ 122 | { 123 | int rtn= -1; 124 | 125 | DBT key= { 126 | .data= self->addr, 127 | .size= strlen(self->addr) 128 | }, 129 | data; 130 | 131 | memset(&data, 0, sizeof(data)); 132 | 133 | /* Read from the database */ 134 | int rc= ez_db_get(db, NULL, &key, &data, 0); 135 | if(DB_NOTFOUND == rc) return rc; 136 | 137 | /* Now put all obsv's in place */ 138 | DS_reset(&self->stack); 139 | 140 | /* Compute number of items we fetched */ 141 | unsigned nItems= data.size / sizeof(struct obsv); 142 | 143 | /* Load them into the stack */ 144 | for(unsigned i= 0; i < nItems; ++i) { 145 | struct obsv *src= (struct obsv*)data.data + i; 146 | DS_push(&self->stack, src); 147 | } 148 | 149 | rtn= 0; 150 | abort: 151 | return rtn; 152 | } 153 | 154 | static int obsv_print(struct obsv *self, FILE *fh) 155 | /******************************************************** 156 | * Print observation to fh 157 | */ 158 | { 159 | ez_fprintf(fh, "\tpos= %lu, len= %hu\n", (long unsigned)self->pos, self->len); 160 | return 0; 161 | } 162 | 163 | 164 | int 165 | ObsvTpl_print(ObsvTpl *self, FILE *fh) 166 | /******************************************************** 167 | * Print a human readable representation of *self. 168 | */ 169 | { 170 | ez_fprintf(fh, "ObsvTpl %s {\n", self->addr); 171 | 172 | DS_visitAllEntries(&self->stack, (int(*)(void*,void*))obsv_print, fh); 173 | ez_fprintf(fh, "}\n"); 174 | return 0; 175 | } 176 | 177 | struct infoTuple { 178 | gzFile fh; 179 | AddrRPT *ar; 180 | LOGFILE *lf; 181 | }; 182 | 183 | static int 184 | obsv_load_AddrRPT(struct obsv *self, struct infoTuple *it) 185 | /******************************************************** 186 | * load specific observation into it->ar. 187 | */ 188 | { 189 | static char lbuf[1024]; 190 | assert(self->len < sizeof(lbuf)); 191 | unsigned len= MIN(self->len, sizeof(lbuf)-1); 192 | 193 | /* Put null terminator in place */ 194 | lbuf[len]= '\0'; 195 | 196 | ez_gzseek(it->fh, self->pos, SEEK_SET); 197 | ez_gzread(it->fh, lbuf, len); 198 | AddrRPT_addLine(it->ar, it->lf, lbuf); 199 | return 0; 200 | } 201 | 202 | int 203 | ObsvTpl_put_AddrRPT(ObsvTpl *self, gzFile fh, AddrRPT *ar) 204 | /******************************************************** 205 | * Place contents of self into ar. 206 | */ 207 | { 208 | struct infoTuple it= {.fh= fh, .ar= ar, .lf= self->lf}; 209 | DS_visitAllEntries(&self->stack, (int(*)(void*,void*))obsv_load_AddrRPT, &it); 210 | return 0; 211 | } 212 | 213 | -------------------------------------------------------------------------------- /maxoff.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #include 20 | 21 | #include "ban2fail.h" 22 | #include "cntry.h" 23 | #include "maxoff.h" 24 | 25 | static struct { 26 | int is_init; 27 | MAP cntry_map, 28 | addr_map; 29 | } S; 30 | 31 | static void 32 | initialize(void) 33 | /******************************************************** 34 | * Perform one-time initializations. 35 | */ 36 | { 37 | S.is_init= 1; 38 | MAP_constructor(&S.cntry_map, 10, 10); 39 | MAP_constructor(&S.addr_map, N_ADDRESSES_HINT/BUCKET_DEPTH_HINT, BUCKET_DEPTH_HINT); 40 | } 41 | 42 | // Compiler doesn't like that we use integers in place of item pointers */ 43 | #pragma GCC diagnostic push 44 | #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" 45 | #pragma GCC diagnostic push 46 | #pragma GCC diagnostic ignored "-Wint-conversion" 47 | 48 | int 49 | MAXOFF_allowed(const char *addr) 50 | /******************************************************** 51 | * Returns the maximum number of allowed offenses. 52 | * -1 means unlimited. 53 | */ 54 | { 55 | if(!S.is_init) 56 | initialize(); 57 | 58 | /* Default is no offenses allowed */ 59 | int rtn= 0; 60 | 61 | /* Check for by-address specification */ 62 | rtn= MAP_findStrItem(&S.addr_map, addr); 63 | 64 | /* by-address spec trumps by-country spec */ 65 | if(!rtn) { 66 | const char *cntry; 67 | cntry= COUNTRY_get_code(addr); 68 | /* if the source country of an address is not known, 69 | * then it will be keyed in our map under "unknown". 70 | */ 71 | cntry= cntry ? cntry : "unknown"; 72 | rtn= MAP_findStrItem(&S.cntry_map, cntry); 73 | } 74 | 75 | return rtn; 76 | } 77 | 78 | int 79 | MAXOFF_init(CFGMAP *h_cfgmap, char *pfix) 80 | /************************************************************** 81 | * Initialize objects from configuration map. 82 | */ 83 | { 84 | if(!S.is_init) 85 | initialize(); 86 | 87 | int rtn= -1; 88 | 89 | size_t len= strlen(pfix)+1024; 90 | char symBuf[len]; 91 | unsigned arr_sz= CFGMAP_numTuples(h_cfgmap); 92 | struct CFGMAP_tuple rtn_arr[arr_sz]; 93 | int nAllowed; 94 | 95 | /* Get the allowed number from pfix */ 96 | const char *str= strrchr(pfix, '\\'); 97 | ++str; 98 | if(1 != sscanf(str, "%d", &nAllowed)) { 99 | eprintf("ERROR: \"%s\" is not an integer number.", str); 100 | goto abort; 101 | } 102 | 103 | { /*--- Register IP entries ---*/ 104 | snprintf(symBuf, len, "%s\\IP", pfix); 105 | 106 | unsigned nFound= CFGMAP_find_tuples(h_cfgmap, rtn_arr, symBuf); 107 | for(unsigned i= 0; i < nFound; ++i) { 108 | const struct CFGMAP_tuple *tpl= rtn_arr + i; 109 | 110 | /* Break the address into prefix & subnet bits */ 111 | static char addr[43]; 112 | unsigned bits; 113 | 114 | int rc= sscanf(tpl->value, "%42[0-9a-zA-Z:.]/%u", addr, &bits); 115 | 116 | if(1 != rc && 2 != rc) { 117 | eprintf("ERROR: \"%s\" is neither IP address or CIDR.", tpl->value); 118 | goto abort; 119 | } 120 | 121 | /* If it's simply an IP address, place in map & keep going */ 122 | if(1 == rc) { 123 | /* Place in the map the number allowed as if it were 124 | * a pointer to an object (there is no object in this case). 125 | */ 126 | MAP_addStrKey(&S.addr_map, addr, (void*)nAllowed); 127 | continue; 128 | } 129 | 130 | /* Avoid stupidity right off the hop */ 131 | if(strchr(addr, ':')) { 132 | eprintf("ERROR: CIDR not implemented for ipv6 \"%s\"", tpl->value); 133 | goto abort; 134 | } else if(16 > bits) { 135 | eprintf("ERROR: Subnet is too large! \"%s\"", tpl->value); 136 | goto abort; 137 | } 138 | 139 | /*--- Expand the CIDR notation to addresses ---*/ 140 | unsigned q1, q2, q3, q4; 141 | 142 | /* Convert quad values from text to binary */ 143 | rc= sscanf(addr, "%u.%u.%u.%u", &q1, &q2, &q3, &q4); 144 | 145 | /* Convert quads into useful parameters */ 146 | uint32_t baddr= (q1 << 24) | (q2 << 16) | (q3 << 8) | q4, 147 | mask= 0xffffffff << (32-bits), 148 | net= baddr & mask, 149 | nAddr= 0xffffffff >> bits; 150 | 151 | assert(4 == rc); 152 | 153 | /* Generate individual addresses, and place them in the map */ 154 | for(unsigned i= 0; i < nAddr; ++i) { 155 | baddr= net | i; 156 | q1= (baddr & 0xff000000) >> 24; 157 | q2= (baddr & 0x00ff0000) >> 16; 158 | q3= (baddr & 0x0000ff00) >> 8; 159 | q4= baddr & 0x000000ff; 160 | 161 | /* Convert back to text form */ 162 | snprintf(addr, sizeof(addr), "%u.%u.%u.%u", q1, q2, q3, q4); 163 | /* Add to the map */ 164 | MAP_addStrKey(&S.addr_map, addr, (void*)nAllowed); 165 | } 166 | } 167 | } 168 | 169 | { /*--- Register COUNTRY entries ---*/ 170 | snprintf(symBuf, len, "%s\\COUNTRY", pfix); 171 | unsigned nFound= CFGMAP_find_tuples(h_cfgmap, rtn_arr, symBuf); 172 | 173 | for(unsigned i= 0; i < nFound; ++i) { 174 | const struct CFGMAP_tuple *tpl= rtn_arr + i; 175 | 176 | /* Place in the map the number allowed as if it were 177 | * a pointer to an object (superflous in this case). 178 | */ 179 | MAP_addStrKey(&S.cntry_map, tpl->value, (void*)nAllowed); 180 | 181 | } 182 | } 183 | 184 | rtn= 0; 185 | abort: 186 | return rtn; 187 | } 188 | 189 | #pragma GCC diagnostic pop 190 | #pragma GCC diagnostic pop 191 | 192 | -------------------------------------------------------------------------------- /ez_libz.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #define _GNU_SOURCE 20 | #include 21 | 22 | #include "ez_libz.h" 23 | #include "util.h" 24 | 25 | /***************************************************/ 26 | ez_proto (gzFile, gzopen, 27 | const char *path, 28 | const char *mode) 29 | { 30 | gzFile rtn= gzopen(path, mode); 31 | if(rtn) return rtn; 32 | 33 | _sys_eprintf((const char*(*)(int))strerror 34 | #ifdef DEBUG 35 | , fileName, lineNo, funcName 36 | #endif 37 | , "ERROR: gzopen()"); 38 | abort(); 39 | } 40 | 41 | /***************************************************/ 42 | ez_proto (int, gzclose, gzFile file) 43 | { 44 | int err= gzclose(file); 45 | if(Z_OK == err) return Z_OK; 46 | 47 | const char *msg="Unknow error"; 48 | 49 | switch(err) { 50 | 51 | case Z_ERRNO: 52 | _sys_eprintf((const char*(*)(int))strerror 53 | #ifdef DEBUG 54 | , fileName, lineNo, funcName 55 | #endif 56 | , "ERROR: gzclose()"); 57 | abort(); 58 | 59 | case Z_STREAM_ERROR: 60 | msg= "File not valid"; 61 | break; 62 | 63 | case Z_MEM_ERROR: 64 | msg= "Out of memory"; 65 | break; 66 | 67 | case Z_BUF_ERROR: 68 | msg= "Read ended in middle of a stream"; 69 | break; 70 | 71 | } 72 | _eprintf( 73 | #ifdef DEBUG 74 | fileName, lineNo, funcName, 75 | #endif 76 | "ERROR: gzclose() [ %s ]", msg); 77 | abort(); 78 | } 79 | 80 | /***************************************************/ 81 | ez_proto (int, gzwrite, 82 | gzFile file, 83 | voidpc buf, 84 | unsigned len) 85 | { 86 | int n= gzwrite(file, buf, len); 87 | if(n == len) return n; 88 | 89 | int err; 90 | const char *str= gzerror(file, &err); 91 | if(Z_ERRNO == err) { 92 | _sys_eprintf((const char*(*)(int))strerror 93 | #ifdef DEBUG 94 | , fileName, lineNo, funcName 95 | #endif 96 | , "ERROR: gzwrite()"); 97 | } else { 98 | _eprintf( 99 | #ifdef DEBUG 100 | fileName, lineNo, funcName, 101 | #endif 102 | "ERROR: gzwrite() [ %s ]", str); 103 | } 104 | abort(); 105 | } 106 | 107 | /***************************************************/ 108 | ez_proto (int, gzread, 109 | gzFile file, 110 | voidp buf, 111 | unsigned len) 112 | { 113 | int n= gzread(file, buf, len); 114 | if(-1 != n) return n; 115 | 116 | int err; 117 | const char *str= gzerror(file, &err); 118 | if(Z_ERRNO == err) { 119 | _sys_eprintf((const char*(*)(int))strerror 120 | #ifdef DEBUG 121 | , fileName, lineNo, funcName 122 | #endif 123 | , "ERROR: gzread()"); 124 | } else { 125 | _eprintf( 126 | #ifdef DEBUG 127 | fileName, lineNo, funcName, 128 | #endif 129 | "ERROR: gzread() [ %s ]", str); 130 | } 131 | abort(); 132 | } 133 | 134 | /***************************************************/ 135 | ez_proto (int, gzflush, gzFile file, int flush) 136 | { 137 | int err= gzflush(file, flush); 138 | if(Z_OK == err) return Z_OK; 139 | 140 | const char *str= gzerror(file, &err); 141 | if(Z_ERRNO == err) { 142 | _sys_eprintf((const char*(*)(int))strerror 143 | #ifdef DEBUG 144 | , fileName, lineNo, funcName 145 | #endif 146 | , "ERROR: gzflush()"); 147 | } else { 148 | _eprintf( 149 | #ifdef DEBUG 150 | fileName, lineNo, funcName, 151 | #endif 152 | "ERROR: gzflush() [ %s ]", str); 153 | } 154 | abort(); 155 | } 156 | 157 | /***************************************************/ 158 | ez_proto (z_off_t, gzseek, 159 | gzFile file, 160 | z_off_t offset, 161 | int whence) 162 | { 163 | z_off_t rtn= gzseek(file, offset, whence); 164 | if(-1 != rtn) return rtn; 165 | 166 | int err; 167 | const char *str= gzerror(file, &err); 168 | if(Z_ERRNO == err) { 169 | _sys_eprintf((const char*(*)(int))strerror 170 | #ifdef DEBUG 171 | , fileName, lineNo, funcName 172 | #endif 173 | , "ERROR: gzseek()"); 174 | } else { 175 | _eprintf( 176 | #ifdef DEBUG 177 | fileName, lineNo, funcName, 178 | #endif 179 | "ERROR: gzseek() [ %s ]", str); 180 | } 181 | abort(); 182 | } 183 | 184 | /***************************************************/ 185 | ez_proto (char*, gzgets, 186 | gzFile file, 187 | char *buf, 188 | int len) 189 | { 190 | char *rtn= gzgets(file, buf, len); 191 | 192 | if(!rtn) { 193 | int err; 194 | const char *str= gzerror(file, &err); 195 | if(Z_OK != err && Z_STREAM_END != err) { 196 | if(Z_ERRNO == err) { 197 | _sys_eprintf((const char*(*)(int))strerror 198 | #ifdef DEBUG 199 | , fileName, lineNo, funcName 200 | #endif 201 | , "ERROR: gzgets()"); 202 | } else { 203 | _eprintf( 204 | #ifdef DEBUG 205 | fileName, lineNo, funcName, 206 | #endif 207 | "ERROR: gzgets() [ %s ]", str); 208 | } 209 | abort(); 210 | } 211 | } 212 | 213 | return rtn; 214 | } 215 | 216 | /***************************************************/ 217 | ez_proto (z_off_t, gztell, 218 | gzFile file) 219 | { 220 | z_off_t rtn= gztell(file); 221 | if(-1 != rtn) return rtn; 222 | 223 | int err; 224 | const char *str= gzerror(file, &err); 225 | if(Z_ERRNO == err) { 226 | _sys_eprintf((const char*(*)(int))strerror 227 | #ifdef DEBUG 228 | , fileName, lineNo, funcName 229 | #endif 230 | , "ERROR: gztell()"); 231 | } else { 232 | _eprintf( 233 | #ifdef DEBUG 234 | fileName, lineNo, funcName, 235 | #endif 236 | "ERROR: gztell() [ %s ]", str); 237 | } 238 | abort(); 239 | } 240 | -------------------------------------------------------------------------------- /map.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | map.h - description 3 | 4 | Generic hashed map class. 5 | ------------------- 6 | begin : Thu Jul 12 2001 7 | copyright : (C) 2001 by John D. Robertson 8 | email : john@rrci.com 9 | ***************************************************************************/ 10 | 11 | /*************************************************************************** 12 | * * 13 | * This program is free software; you can redistribute it and/or modify * 14 | * it under the terms of the GNU General Public License as published by * 15 | * the Free Software Foundation; either version 2 of the License, or * 16 | * (at your option) any later version. * 17 | * * 18 | ***************************************************************************/ 19 | #ifndef MAP_H 20 | #define MAP_H 21 | 22 | #include "ptrvec.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Structure req'd for each map */ 29 | typedef struct { 30 | PTRVEC* bucketArr; 31 | unsigned int numBuckets; 32 | } MAP; 33 | 34 | /***************** Function prototypes and macros *******************/ 35 | #define MAP_is_init(s) \ 36 | ((s)->bucketArr) 37 | 38 | MAP* 39 | MAP_constructor(MAP *self, 40 | unsigned int numBuckets, 41 | unsigned int slotsPerBucket); 42 | /**************************************************************** 43 | * Construct a map with numBuckets buckets. slotsPerBucket provides 44 | * an initial sizing of the buckets, but they can grow dynamically. 45 | */ 46 | 47 | #define MAP_create(self, numBuckets, slotsPerBucket)\ 48 | (MAP_constructor((self)=malloc(sizeof(MAP)), numBuckets, slotsPerBucket) ? (self) : ( self ? realloc(MAP_destructor(self),0): 0)) 49 | /*********************************************************** 50 | * Same as constructor with the addition of the object being 51 | * malloc()'ed for you. 52 | */ 53 | 54 | int 55 | MAP_sinit(MAP *self, 56 | unsigned int numBuckets, 57 | unsigned int slotsPerBucket); 58 | /*********************************************************** 59 | * Initialize or clear() for a static instance. 60 | */ 61 | 62 | void* 63 | MAP_destructor(MAP *self); 64 | /************************************************ 65 | * Free resources associated with object. 66 | */ 67 | 68 | #define MAP_destroy(s)\ 69 | {if(MAP_destructor(s)) {free(s); (s)=NULL;}} 70 | /*********************************************************** 71 | * Same as destructor with the addition of freeing the object. 72 | */ 73 | 74 | int 75 | MAP_clearAndDestroy(MAP *self, void *(* destructor)(void *item_ptr)); 76 | /**************************************************************** 77 | * Call destructors on all item_ptr's and free() them, and 78 | * free() all key records. 79 | */ 80 | 81 | #define MAP_clear(self) \ 82 | MAP_clearAndDestroy(self, NULL) 83 | /**************************************************************** 84 | * free() all key records. 85 | */ 86 | 87 | int 88 | MAP_addKey(MAP *self, 89 | const void *key_ptr, 90 | unsigned int keyLen, 91 | void *item_ptr); 92 | /********************************************************************************* 93 | * Add a key to map, no checking for duplicates. 94 | */ 95 | 96 | #define MAP_addTypedKey(self, key, item_ptr) \ 97 | MAP_addKey(self, &(key), sizeof(key), item_ptr) 98 | 99 | #define MAP_addStrKey(self, keystr, item_ptr) \ 100 | MAP_addKey(self, keystr, strlen(keystr), item_ptr) 101 | 102 | void* 103 | MAP_findItem(MAP *self, 104 | const void *key_ptr, 105 | unsigned int keyLen); 106 | /****************************************************************************** 107 | * Find the the first matching key and return it's item_ptr. 108 | * Returns: 109 | * NULL Not found 110 | * item_ptr first one found 111 | */ 112 | #define MAP_findTypedItem(self, key) \ 113 | MAP_findItem(self, &(key), sizeof(key)) 114 | 115 | #define MAP_findStrItem(self, keystr) \ 116 | MAP_findItem(self, keystr, strlen(keystr)) 117 | 118 | void* 119 | MAP_removeItem(MAP *self, 120 | const void *key_ptr, 121 | unsigned int keyLen); 122 | /****************************************************************************** 123 | * Find the the first matching key and remove it from the map. 124 | * Returns: 125 | * NULL Not found 126 | * item_ptr first one found 127 | */ 128 | #define MAP_removeTypedItem(self, key) \ 129 | MAP_removeItem(self, &(key), sizeof(key)) 130 | 131 | #define MAP_removeStrItem(self, keystr) \ 132 | MAP_removeItem(self, keystr, strlen(keystr)) 133 | 134 | void* 135 | MAP_removeSpecificItem(MAP *self, 136 | const void *key_ptr, 137 | unsigned int keyLen, 138 | void *pItem); 139 | /****************************************************************************** 140 | * Find the first matching key and pointer, and remove it from the map. 141 | * pItem is the address of the specific item to be removed. 142 | * Returns: 143 | * NULL Not found 144 | * item_ptr first one found 145 | */ 146 | #define MAP_removeSpecificTypedItem(self, key, pItem) \ 147 | MAP_removeSpecificItem(self, &(key), sizeof(key), pItem) 148 | 149 | #define MAP_removeSpecificStrItem(self, keystr, pItem) \ 150 | MAP_removeSpecificItem(self, keystr, strlen(keystr), pItem) 151 | 152 | int 153 | MAP_findItems(MAP *self, 154 | void* rtnArr[], 155 | unsigned int rtnArrSize, 156 | const void *key_ptr, 157 | unsigned int keyLen); 158 | /****************************************************************************** 159 | * Find all matching key(s) in the map, and put the accompanying item_ptr's 160 | * into the rtnArr. Returns: 161 | * -1 Insufficient space in rtnArr 162 | * 0 .. INT_MAX Number of item_ptr's returned in rtnArr 163 | */ 164 | 165 | #define MAP_findTypedItems(self, rtnArr, rtnArrSize, key) \ 166 | MAP_findItems(self, rtnArr, rtnArrSize, &(key), sizeof(key)) 167 | 168 | #define MAP_findStrItems(self, rtnArr, rtnArrSize, keystr) \ 169 | MAP_findItems(self, rtnArr, rtnArrSize, keystr, strlen(keystr)) 170 | 171 | int 172 | MAP_visitAllEntries(MAP *self, int (* func)(void *item_ptr, void *data), void *data); 173 | /****************************************************************************** 174 | * Visit all entries in the map. if (*func) returns nonzero, then 175 | * the process stops and MAP_visitAllEntries will return non-zero. 176 | */ 177 | 178 | void 179 | MAP_fetchAllItems(MAP *self, void **rtn_arr); 180 | /****************************************************************************** 181 | * Place the item pointers into the supplied array. 182 | */ 183 | 184 | unsigned 185 | MAP_numItems(MAP *self); 186 | /****************************************************************************** 187 | * Return a count of the items indexed in the map. 188 | */ 189 | 190 | #ifdef __cplusplus 191 | } 192 | #endif 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /str.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef STR_H 20 | #define STR_H 21 | 22 | #include 23 | #include 24 | 25 | /* STR is a dynamically sized null terminated string buffer which is always 26 | * appended until STR_reset() is called. It is particularly useful for 27 | * things like creating complex SQL queries. 28 | */ 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | typedef struct _cb { 35 | size_t sz, 36 | len; 37 | 38 | char *buf; 39 | } STR; 40 | 41 | #define STR_str(self) \ 42 | ((const char*)(self)->buf) 43 | /********************************************************************************** 44 | * Return the pointer to the buffer. 45 | */ 46 | 47 | #define STR_len(self) \ 48 | ((const size_t)(self)->len) 49 | /********************************************************************************** 50 | * Return the current length of the string in the buffer 51 | */ 52 | 53 | #define STR_reset(self) \ 54 | ((self)->buf[((self)->len= 0)]= '\0') 55 | /********************************************************************************** 56 | * Reset the buffer so that the length is zero. 57 | */ 58 | 59 | int 60 | STR_sinit(STR *self, size_t sz_hint); 61 | /********************************************************************************** 62 | * Initialization to be called for static instances of STR each use, but 63 | * actual initialization only occurs once. 64 | */ 65 | 66 | #define STR_create(p)\ 67 | ((p)= (STR_constructor((p)=malloc(sizeof(STR))) ? (p) : ( p ? realloc(STR_destructor(p),0): 0))) 68 | STR* 69 | STR_constructor(STR *self, size_t sz_hint); 70 | /********************************************************************************** 71 | * Prepare a STR for use with initial size of sz_hint. 72 | */ 73 | 74 | 75 | #define STR_destroy(self)\ 76 | if(STR_destructor(self)){free(self);(self)=NULL;} 77 | void* 78 | STR_destructor(STR *self); 79 | /********************************************************************************** 80 | * Free resources associated with STR. 81 | */ 82 | 83 | int 84 | STR_sprintf(STR *self, const char *fmt, ...); 85 | /********************************************************************************** 86 | * Same as sprintf, except you don't have to worry about buffer overflows. 87 | * Returns -1 for error. 88 | */ 89 | 90 | int 91 | STR_vsprintf(STR *self, const char *fmt, va_list ap); 92 | /********************************************************************************** 93 | * Same as vsprintf, except you don't have to worry about buffer overflows. 94 | * Returns -1 for error. 95 | */ 96 | 97 | int 98 | STR_append(STR *self, const char *str, size_t str_len); 99 | /********************************************************************************** 100 | * Append string str to the end of the current buffer. 101 | * Returns -1 for error. 102 | */ 103 | 104 | int 105 | STR_putc(STR *self, int c); 106 | /********************************************************************************** 107 | * Append a single character to the end of the current buffer. 108 | * Returns -1 for error. 109 | */ 110 | 111 | const char* 112 | STR_tolower(STR *self); 113 | /********************************************************************************** 114 | * Convert all characters in buffer to lower case. 115 | */ 116 | 117 | const char* 118 | STR_XMLencode(STR *self, const char *src); 119 | /************************************************************** 120 | * encode the src string for XML into self. Return self's buffer. 121 | * NOTE: self does not get reset! 122 | */ 123 | 124 | const char* 125 | STR_URLencode(STR *self, const char *src); 126 | /************************************************************** 127 | * encode the src string for URL into self. Return self's buffer. 128 | * NOTE: self does not get reset! 129 | */ 130 | 131 | const char* 132 | STR_utf8toHTML(STR *self, const char *src); 133 | /************************************************************** 134 | * place the HTML representation of the utf-8 src string into self. 135 | * Return self's buffer. 136 | * NOTE: self does not get reset! 137 | */ 138 | 139 | const char* 140 | STR_escapeJSONstr(STR *self, const char *src); 141 | /************************************************************** 142 | * Escape any characters such the src can be used in a JSON 143 | * string. 144 | * Return self's buffer. 145 | * NOTE: self does not get reset! 146 | */ 147 | 148 | #ifdef __cplusplus 149 | } 150 | 151 | // C++ wrapper 152 | 153 | class StrBuf { 154 | public: 155 | StrBuf(size_t sz_hint) 156 | {STR_constructor(&obj, sz_hint);} 157 | 158 | ~StrBuf() 159 | {STR_destructor(&obj);} 160 | 161 | inline const char *str() const 162 | {return STR_str(&obj);} 163 | 164 | inline size_t len() const 165 | {return STR_len(&obj);} 166 | 167 | inline void reset() 168 | {STR_reset(&obj);} 169 | 170 | inline int sprintf(const char *fmt, ...) 171 | { 172 | va_list ap; 173 | va_start (ap, fmt); 174 | int rtn= STR_vsprintf(&obj, fmt, ap); 175 | va_end (ap); 176 | return rtn; 177 | } 178 | 179 | inline int vsprintf(const char *fmt, va_list ap) 180 | { 181 | return STR_vsprintf(&obj, fmt, ap); 182 | } 183 | 184 | inline int append(const char *str, size_t str_len) 185 | {return STR_append(&obj, str, str_len);} 186 | 187 | inline int putc(int c) 188 | {return STR_putc(&obj, c);} 189 | 190 | inline const char* tolower() 191 | {return STR_tolower(&obj);} 192 | 193 | inline const char* XMLencode(const char *src) 194 | {return STR_XMLencode(&obj, src);} 195 | 196 | inline const char* URLencode(const char *src) 197 | {return STR_URLencode(&obj, src);} 198 | 199 | inline const char* utf8toHTML(const char *src) 200 | {return STR_utf8toHTML(&obj, src);} 201 | 202 | private: 203 | STR obj; 204 | }; 205 | #endif 206 | 207 | #endif 208 | -------------------------------------------------------------------------------- /ptrvec.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2008 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the GNU General Public License * 16 | * along with this program; if not, write to the * 17 | * Free Software Foundation, Inc., * 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 19 | ***************************************************************************/ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "ptrvec.h" 26 | 27 | 28 | static int 29 | grow (PTRVEC * self) 30 | { 31 | if (PTRVEC_resize (self, self->maxItems * 2)) 32 | { 33 | if (PTRVEC_resize (self, self->maxItems + self->maxItems / 2)) 34 | { 35 | if (PTRVEC_resize (self, self->maxItems + self->maxItems / 4)) 36 | return 1; 37 | } 38 | } 39 | return 0; 40 | } 41 | 42 | int 43 | PTRVEC_find (PTRVEC * self, unsigned int *ndxBuf, void *item) 44 | { 45 | unsigned int i; 46 | void *ptr; 47 | 48 | PTRVEC_loopFwd (self, i, ptr) 49 | { 50 | if (ptr == item) 51 | { 52 | if(ndxBuf) *ndxBuf = (self->head + i) % self->maxItems; 53 | return 1; 54 | } 55 | } 56 | return 0; 57 | } 58 | 59 | int 60 | PTRVEC_sinit(PTRVEC *self, unsigned initMaxItems) 61 | /*********************************************** 62 | * Static initialization call. 63 | */ 64 | { 65 | int rtn= 1; 66 | 67 | if(!(self->ptrArr)) { 68 | if(!(PTRVEC_constructor(self, initMaxItems))) goto abort; 69 | } else { 70 | PTRVEC_reset(self); 71 | } 72 | 73 | rtn= 0; 74 | abort: 75 | return rtn; 76 | } 77 | 78 | PTRVEC * 79 | PTRVEC_constructor (PTRVEC * self, unsigned int initMaxItems) 80 | { 81 | if (!self) return NULL; 82 | memset (self, 0, sizeof (*self)); 83 | if (!(self->ptrArr = malloc (initMaxItems * sizeof (void*)))) return NULL; 84 | 85 | self->maxItems = initMaxItems; 86 | return self; 87 | } 88 | 89 | void * 90 | PTRVEC_destructor (PTRVEC * self) 91 | { 92 | if (self->ptrArr) free (self->ptrArr); 93 | if(self->sortBuf) free(self->sortBuf); 94 | return self; 95 | } 96 | 97 | int 98 | PTRVEC_sort (PTRVEC * self, int (*cmp) (const void *const*, const void *const*)) 99 | { 100 | void *ptr; 101 | unsigned int i, sz; 102 | unsigned int numItems = self->numItems;; 103 | 104 | /* Nothing to sort */ 105 | if(!numItems) return 0; 106 | 107 | /* Compute how large the sort buffer needs to be */ 108 | sz= numItems * sizeof (void *); 109 | 110 | /* If there is no sort buffer, or it isn't big enough, allocate more */ 111 | if(sz > self->sortBuf_sz) { 112 | if(self->sortBuf) free(self->sortBuf); 113 | self->sortBuf_sz= 0; 114 | if(!(self->sortBuf= malloc(sz))) return 1; 115 | self->sortBuf_sz= sz; 116 | } 117 | // if (!(block = malloc (numItems * sizeof (void *)))) return 1; 118 | 119 | 120 | PTRVEC_loopFwd (self, i, ptr) self->sortBuf[i] = ptr; 121 | PTRVEC_reset (self); 122 | 123 | qsort(self->sortBuf, numItems, sizeof (void *), (int(*)(const void*, const void*))cmp); 124 | for (i = 0; i < numItems; i++) { 125 | PTRVEC_addTail (self, self->sortBuf[i]); 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | 132 | int 133 | PTRVEC_resize (PTRVEC * self, unsigned int maxItems) 134 | { 135 | unsigned int headSize; 136 | void *tmp; 137 | 138 | if (!maxItems) 139 | return 0; 140 | if (maxItems < self->numItems) 141 | return 1; 142 | 143 | if (!(tmp = realloc (self->ptrArr, maxItems * sizeof (void*)))) 144 | return 1; 145 | self->ptrArr = tmp; 146 | 147 | if (self->head > self->tail) 148 | { 149 | headSize = self->maxItems - self->head; 150 | memmove (self->ptrArr + maxItems - headSize, 151 | self->ptrArr + self->maxItems - headSize, 152 | headSize * sizeof (*self->ptrArr)); 153 | self->head = maxItems - headSize; 154 | } 155 | 156 | self->maxItems = maxItems; 157 | 158 | return 0; 159 | } 160 | 161 | 162 | void * 163 | PTRVEC_addHead (PTRVEC * self, void *ptr) 164 | { 165 | if (self->numItems == self->maxItems && grow (self)) 166 | return NULL; 167 | 168 | if (self->numItems) 169 | self->head = (self->head + self->maxItems - 1) % self->maxItems; 170 | 171 | self->ptrArr[self->head] = ptr; 172 | self->numItems++; 173 | return ptr; 174 | } 175 | 176 | void * 177 | PTRVEC_remHead (PTRVEC * self) 178 | { 179 | void *tmp; 180 | 181 | if (!self->numItems) 182 | return NULL; 183 | self->numItems--; 184 | tmp = self->ptrArr[self->head]; 185 | if (self->numItems) 186 | self->head = (self->head + 1) % self->maxItems; 187 | 188 | return tmp; 189 | } 190 | 191 | void * 192 | PTRVEC_addTail (PTRVEC * self, void *ptr) 193 | { 194 | if (self->numItems == self->maxItems && grow (self)) 195 | return NULL; 196 | 197 | if (self->numItems) 198 | self->tail = (self->tail + 1) % self->maxItems; 199 | 200 | self->ptrArr[self->tail] = ptr; 201 | self->numItems++; 202 | return ptr; 203 | } 204 | 205 | void * 206 | PTRVEC_remTail (PTRVEC * self) 207 | { 208 | void *tmp; 209 | 210 | if (!self->numItems) 211 | return NULL; 212 | self->numItems--; 213 | tmp = self->ptrArr[self->tail]; 214 | 215 | if (self->numItems) 216 | self->tail = (self->tail + self->maxItems - 1) % self->maxItems; 217 | return tmp; 218 | } 219 | 220 | void * 221 | PTRVEC_remove (PTRVEC * self, void *item) 222 | { 223 | unsigned int blockLen; 224 | unsigned int ndx; 225 | 226 | if (!PTRVEC_find (self, &ndx, item)) 227 | return NULL; 228 | 229 | if (self->numItems == 1) 230 | { 231 | self->head = self->tail = 0; 232 | } 233 | else if (ndx == self->head) 234 | { 235 | self->head = (self->head + 1) % self->maxItems; 236 | } 237 | else if (ndx == self->tail) 238 | { 239 | self->tail = (self->tail + self->maxItems - 1) % self->maxItems; 240 | } 241 | else if (ndx < self->tail) /* Non contiguous, top block */ 242 | { 243 | blockLen = self->tail - ndx; 244 | memmove (self->ptrArr + ndx, 245 | self->ptrArr + ndx + 1, blockLen * sizeof (*self->ptrArr)); 246 | self->tail--; 247 | } 248 | else /* Contiguous or non contiguous bottom block */ 249 | { 250 | blockLen = ndx - self->head; 251 | memmove (self->ptrArr + self->head + 1, 252 | self->ptrArr + self->head, blockLen * sizeof (*self->ptrArr)); 253 | self->head++; 254 | } 255 | 256 | self->numItems--; 257 | return item; 258 | } 259 | 260 | #ifdef DEBUG 261 | void 262 | PTRVEC_assert_integrity(PTRVEC *self) 263 | { 264 | char *p, val; 265 | unsigned i; 266 | PTRVEC_loopFwd(self, i, p) { 267 | val= *p; 268 | } 269 | } 270 | #endif 271 | -------------------------------------------------------------------------------- /ptrvec.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2008 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the GNU General Public License * 16 | * along with this program; if not, write to the * 17 | * Free Software Foundation, Inc., * 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 19 | ***************************************************************************/ 20 | 21 | #ifndef PTRVEC_H 22 | #define PTRVEC_H 23 | 24 | typedef struct 25 | { 26 | void **ptrArr; 27 | unsigned int maxItems, numItems, head, tail; 28 | 29 | void **sortBuf; 30 | unsigned sortBuf_sz; 31 | } 32 | PTRVEC; 33 | 34 | #ifdef __cplusplus 35 | extern "C" 36 | { 37 | #endif 38 | 39 | #define PTRVEC_arr(self) \ 40 | ((self)->ptrArr) 41 | 42 | #define PTRVEC_is_init(self) \ 43 | PTRVEC_arr(self) 44 | 45 | int 46 | PTRVEC_sinit(PTRVEC *self, unsigned initMaxItems); 47 | /*********************************************** 48 | * Static initialization call. 49 | */ 50 | 51 | PTRVEC *PTRVEC_constructor (PTRVEC * self, unsigned int initMaxItems); 52 | /*********************************************** 53 | * Construct a PTRVEC. 54 | * 55 | * initMaxItems - a guess at how many items it will need to hold. 56 | * returns - pointer to the object, or NULL for failure. 57 | */ 58 | 59 | #define PTRVEC_create(p, initMaxItems) \ 60 | ((p)=(PTRVEC_constructor((p)=malloc(sizeof(PTRVEC)), initMaxItems) ? (p) : ( p ? realloc(PTRVEC_destructor(p),0) : 0 ))) 61 | 62 | void *PTRVEC_destructor (PTRVEC * self); 63 | /*********************************************** 64 | * Destruct a PTRVEC. 65 | */ 66 | 67 | #define PTRVEC_destroy(self) \ 68 | {if(PTRVEC_destructor(self)) {free(self);}} 69 | 70 | void *PTRVEC_addHead (PTRVEC * self, void *ptr); 71 | /*********************************************** 72 | * Add an item to the head of the 'list'. 73 | * 74 | * ptr - pointer to the item to add. 75 | * returns - pointer to the node added, or NULL for failure. 76 | */ 77 | 78 | void *PTRVEC_remHead (PTRVEC * self); 79 | /************************************************ 80 | * Remove an item from the head of the 'list'. 81 | * 82 | * returns - pointer to the item, or NULL if the 'list' is emtpy. 83 | */ 84 | 85 | void *PTRVEC_addTail (PTRVEC * self, void *ptr); 86 | /*********************************************** 87 | * Add an item to the tail of the 'list'. 88 | * 89 | * ptr - pointer to the item to add. 90 | * returns - pointer to the node added, or NULL for failure. 91 | */ 92 | 93 | void *PTRVEC_remTail (PTRVEC * self); 94 | /************************************************ 95 | * Remove an item from the tail of the 'list'. 96 | * 97 | * returns - pointer to the item, or NULL if the 'list' is emtpy. 98 | */ 99 | 100 | int PTRVEC_resize (PTRVEC * self, unsigned int maxItems); 101 | /************************************************ 102 | * Resize the vector. This is normally done automatically 103 | * for you. 104 | * 105 | * maxItems - the new number of items to use in the list. 106 | * returns - nonzero if there is not enough memory, or if maxItems < self->numItems. 107 | */ 108 | 109 | int PTRVEC_sort (PTRVEC * self, int (*cmp) (const void *const*, const void *const*)); 110 | /************************************************ 111 | * Use qsort() to sort the items in the vector according to the cmp function. 112 | * 113 | * cmp - function pointer to use for comparison. 114 | * returns - nonzero for failure (not enough memory for temporary block) 115 | */ 116 | 117 | int PTRVEC_find (PTRVEC * self, unsigned int *ndxBuf, void *item); 118 | /************************************************ 119 | * Searches for an item. If found, returns 0 and writes index number of 120 | * item into ndxBuf. if ndxBuf is not NULL. 121 | * returns 1 if found, 0 if not found. 122 | */ 123 | 124 | void *PTRVEC_remove (PTRVEC * self, void *item); 125 | /*************************************************** 126 | * Remove an item from the PTRVEC. 127 | */ 128 | 129 | #ifdef DEBUG 130 | void 131 | PTRVEC_assert_integrity(PTRVEC *self); 132 | /*************************************************** 133 | * Perform internal integrity checks for corruption. 134 | */ 135 | #endif 136 | 137 | #define PTRVEC_reset(self) \ 138 | (self)->numItems= (self)->head= (self)->tail= 0 139 | /************************************************ 140 | * void PTRVEC_reset(PTRVEC *self); 141 | * Reset the 'list' to contain no items. 142 | */ 143 | 144 | #define PTRVEC_numItems(self) \ 145 | (self)->numItems 146 | /************************************************ 147 | * unsigned int PTRVEC_numItems(PTRVEC *self); 148 | * 149 | * Return the number of items in the 'list'. 150 | */ 151 | 152 | #define PTRVEC_ndxPtr(self, ndx) \ 153 | (ndx>=(self)->numItems?0:(self)->ptrArr[((self)->head+ndx)%(self)->maxItems]) 154 | /************************************************* 155 | * void *PTRVEC_ndxPtr(PTRVEC *self, unsigned int ndx); 156 | * 157 | * get a pointer given it's position in the 'array'. 158 | * 159 | * ndx - index of the position in the 'array' 160 | * returns - pointer, or NULL if the ndx is invalid 161 | */ 162 | 163 | #define PTRVEC_first(self) \ 164 | ((self)->numItems?(self)->ptrArr[(self)->head]:0) 165 | /******************************************************* 166 | * void *PTRVEC_first(PTRVEC *self); 167 | * gets the first pointer in the vector. 168 | * 169 | * returns - pointer to the first item, or NULL if the vector is emtpy. 170 | */ 171 | 172 | #define PTRVEC_last(self) \ 173 | ((self)->numItems?(self)->ptrArr[(self)->tail]:0) 174 | /******************************************************* 175 | * void *PTRVEC_last(PTRVEC *self); 176 | * gets the last pointer in the vector. 177 | * 178 | * returns - pointer to the last item, or NULL if the vector is emtpy. 179 | */ 180 | 181 | 182 | #ifdef __cplusplus 183 | 184 | /* Macros for traversing vector in list like fashion */ 185 | #define PTRVEC_loopFwd(self, i, ptr) \ 186 | for(i=0, ptr= (decltype(ptr))(self)->ptrArr[(self)->head];\ 187 | i < (self)->numItems;\ 188 | ++i, ptr= (decltype(ptr))(self)->ptrArr[((self)->head+i)%(self)->maxItems]) 189 | 190 | #define PTRVEC_loopBkwd(self, i, ptr) \ 191 | for(i=0, ptr= (decltype(ptr))(self)->ptrArr[(self)->tail];\ 192 | i < (self)->numItems;\ 193 | ++i, ptr= (decltype(ptr))(self)->ptrArr[((self)->tail+(self)->maxItems-i)%(self)->maxItems]) 194 | #else 195 | 196 | /* Macros for traversing vector in list like fashion */ 197 | #define PTRVEC_loopFwd(self, i, ptr) \ 198 | for(i=0, ptr= (typeof(ptr))(self)->ptrArr[(self)->head];\ 199 | i < (self)->numItems;\ 200 | ++i, ptr= (typeof(ptr))(self)->ptrArr[((self)->head+i)%(self)->maxItems]) 201 | 202 | #define PTRVEC_loopBkwd(self, i, ptr) \ 203 | for(i=0, ptr= (typeof(ptr))(self)->ptrArr[(self)->tail];\ 204 | i < (self)->numItems;\ 205 | ++i, ptr= (typeof(ptr))(self)->ptrArr[((self)->tail+(self)->maxItems-i)%(self)->maxItems]) 206 | 207 | #endif 208 | 209 | #ifdef __cplusplus 210 | } 211 | #endif 212 | 213 | #endif 214 | -------------------------------------------------------------------------------- /es.h: -------------------------------------------------------------------------------- 1 | #ifndef ES_H 2 | #define ES_H 3 | 4 | /**************************************************************************************** 5 | * ES is short for "Event Server". This is a per-thread event server 6 | * for multiplexing sockets, regular file descriptors, Unix signals, and interval 7 | * timers. 8 | ****************************************************************************************/ 9 | 10 | #ifndef _GNU_SOURCE 11 | # define _GNU_SOURCE 12 | #endif 13 | #include 14 | #include 15 | 16 | #include "ez.h" 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | ez_hdr_proto (int, ES_registerFd, 23 | int fd, 24 | short events, 25 | int (*callback_f)(void *ctxt, int fd, short events), 26 | void *ctxt); 27 | /********************************************************************** 28 | * Register a function to be called when there is activity on the 29 | * file descriptor (which may be a file, socket, pipe, etc. under Unix). 30 | * 31 | * fd: the file descriptor to be registered. 32 | * events: event bits to monitor (see: man 2 poll). 33 | * callback_f: callback function for when activity is detected. 34 | * ctxt: Pointer which will be passed as the first argument to callback_f(). 35 | * 36 | * RETURNS: 37 | * If successful, a positive integer which can be used to unregister the callback. 38 | * On failure, -1 is returned. 39 | */ 40 | #ifdef DEBUG 41 | # define ez_ES_registerFd(...) \ 42 | _ez_ES_registerFd(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 43 | #else 44 | # define ez_ES_registerFd(...) \ 45 | _ez_ES_registerFd(__VA_ARGS__) 46 | #endif 47 | 48 | ez_hdr_proto (int, ES_registerSignal, 49 | int signum, 50 | int (*callback_f)(void *ctxt, int signo), 51 | void *ctxt); 52 | /********************************************************************** 53 | * Register a function to be called when a particular Unix signal is 54 | * raised. Note: callback_f() is not called from a Unix signal handler, 55 | * so it is safe to modify data within callback_f(). 56 | * 57 | * signum: Unix signal number of interest (type "trap -l" on command line to see a list of signals) 58 | * callback_f: callback function for when activity is detected. 59 | * ctxt: Pointer which will be passed as the first argument to callback_f(). 60 | * 61 | * RETURNS: 62 | * If successful, a positive integer which can be used to unregister the callback. 63 | * On failure, -1 is returned. 64 | */ 65 | #ifdef DEBUG 66 | # define ez_ES_registerSignal(...) \ 67 | _ez_ES_registerSignal(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 68 | #else 69 | # define ez_ES_registerSignal(...) \ 70 | _ez_ES_registerSignal(__VA_ARGS__) 71 | #endif 72 | 73 | ez_hdr_proto (int, ES_registerVSignal, 74 | int signum, 75 | int (*callback_f)(void *ctxt,int signo), 76 | void *ctxt); 77 | /********************************************************************** 78 | * Register a function to be called when a particular virtual signal is 79 | * raised. Virtual signals are implemented on top of the Unix signal, SIGUSR2. 80 | * 81 | * signum: Any integer number which is meaningful to your application. 82 | * callback_f: callback function for when activity is detected. 83 | * ctxt: Pointer which will be passed as the first argument to callback_f(). 84 | * 85 | * RETURNS: 86 | * If successful, a positive integer which can be used to unregister the callback. 87 | * On failure, -1 is returned. 88 | */ 89 | #ifdef DEBUG 90 | # define ez_ES_registerVSignal(...) \ 91 | _ez_ES_registerVSignal(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 92 | #else 93 | # define ez_ES_registerVSignal(...) \ 94 | _ez_ES_registerVSignal(__VA_ARGS__) 95 | #endif 96 | 97 | ez_hdr_proto (int, ES_VSignal, 98 | pthread_t tid, 99 | int signum); 100 | /********************************************************************** 101 | * Send a virtual signal to tid, which is multiplexed on SIGUSR2. 102 | * 103 | * tid: Target thread identifier. 104 | * signum: Any integer number which is meaningful to your application. 105 | * 106 | * RETURNS: 107 | * 0: successful 108 | * -1: failures. 109 | */ 110 | #ifdef DEBUG 111 | # define ez_ES_VSignal(...) \ 112 | _ez_ES_VSignal(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 113 | #else 114 | # define ez_ES_VSignal(...) \ 115 | _ez_ES_VSignal(__VA_ARGS__) 116 | #endif 117 | 118 | ez_hdr_proto (int, ES_registerTimer, 119 | int64_t pause_ms, 120 | int64_t interval_ms, 121 | int (*callback_f)(void *ctxt), 122 | void *ctxt 123 | ); 124 | /********************************************************************** 125 | * Register a function to be called when an interval or single-shot 126 | * timer expires. If interval_ms == 0, the timer is single shot, and 127 | * can only be ES_unregister()'d before it expires. 128 | * 129 | * pause_ms: How many milliseconds to wait before initially firing. 130 | * interval_ms: How many milliseconds to wait between successive firings. 131 | * if this is 0, the timer is single shot. 132 | * callback_f: callback function for when timer expires. 133 | * ctxt: Pointer which will be passed as the first argument to callback_f(). 134 | * 135 | * RETURNS: 136 | * If successful, a positive integer which can be used to unregister the callback. 137 | * On failure, -1 is returned. 138 | */ 139 | #ifdef DEBUG 140 | # define ez_ES_registerTimer(...) \ 141 | _ez_ES_registerTimer(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 142 | #else 143 | # define ez_ES_registerTimer(...) \ 144 | _ez_ES_registerTimer(__VA_ARGS__) 145 | #endif 146 | 147 | ez_hdr_proto (int, ES_unregister, 148 | int key); 149 | /********************************************************************** 150 | * Unegister a previously registered callback. 151 | * 152 | * key: value obtained from ES_registerXXX(). 153 | * 154 | * RETURNS: 155 | * 0 for success. 156 | * -1 for failure (key not found) 157 | */ 158 | #ifdef DEBUG 159 | # define ez_ES_unregister(...) \ 160 | _ez_ES_unregister(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 161 | #else 162 | # define ez_ES_unregister(...) \ 163 | _ez_ES_unregister(__VA_ARGS__) 164 | #endif 165 | 166 | ez_hdr_proto (int, ES_run); 167 | /********************************************************************** 168 | * For this thread, use poll() to process socket activity until one 169 | * of the registered callback_f() returns non-zero. 170 | * 171 | * RETURNS: 172 | * Whatever nonzero value callback_f() returned. 173 | */ 174 | #ifdef DEBUG 175 | # define ez_ES_run(...) \ 176 | _ez_ES_run(__FILE__, __LINE__, __func__, ##__VA_ARGS__) 177 | #else 178 | # define ez_ES_run(...) \ 179 | _ez_ES_run(__VA_ARGS__) 180 | #endif 181 | 182 | pthread_t 183 | ES_spawn_thread_sched( 184 | void *(*user_main) (void *), 185 | void *arg, 186 | int sched_policy, /* SCHED_NORMAL || SCHED_FIFO || SCHED_RR || SCHED_BATCH */ 187 | int priority 188 | ); 189 | /********************************************************************** 190 | * Spawn a thread which will begin executing user_main(arg). 191 | * NOTE: the calling thread will be blocked until ES_release_parent() 192 | * is called from user_main()! 193 | * 194 | * user_main: function pointer where thread will execute. 195 | * arg: address passed to user_main(arg). 196 | * sched_policy: Which pthreads scheduling policy to use. 197 | * priority: pthreads priority to use. 198 | * 199 | * RETURNS: 200 | * 0 for success, nonzero for error 201 | */ 202 | 203 | #define ES_spawn_thread(user_main, arg) \ 204 | ES_spawn_thread_sched(user_main, arg, -1, 0) 205 | /********************************************************************** 206 | * This is a convenience macro. 207 | */ 208 | 209 | void 210 | ES_release_parent(void); 211 | /********************************************************************** 212 | * Called by a new thread created with ES_spawn_thread_sched(), so 213 | * that the parent can continue execution. 214 | */ 215 | 216 | void 217 | ES_cleanup(void); 218 | /********************************************************************** 219 | * Called by a thread when it exits, to clean up resources. 220 | */ 221 | 222 | 223 | #ifdef __cplusplus 224 | } 225 | #endif 226 | 227 | 228 | #endif 229 | -------------------------------------------------------------------------------- /offEntry.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #define _GNU_SOURCE 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "ban2fail.h" 27 | #include "cntry.h" 28 | #include "ez_libdb.h" 29 | #include "ez_libc.h" 30 | #include "map.h" 31 | #include "offEntry.h" 32 | #include "util.h" 33 | /********************************************************/ 34 | /**************** OFFENTRY ******************************/ 35 | /********************************************************/ 36 | 37 | static void 38 | common_constructor(OFFENTRY *self) 39 | /****************************************************************** 40 | * common portion for all constructors. 41 | */ 42 | { 43 | memset(self, 0, sizeof(*self)); 44 | } 45 | 46 | OFFENTRY* 47 | OFFENTRY_addr_constructor(OFFENTRY *self, const char *addr) 48 | /******************************************************** 49 | * Prepare for use. 50 | */ 51 | { 52 | OFFENTRY *rtn= NULL; 53 | 54 | common_constructor(self); 55 | 56 | strncpy(self->addr, addr, sizeof(self->addr)-1); 57 | 58 | const char *cntry= COUNTRY_get_code(self->addr); 59 | if(cntry) 60 | strncpy(self->cntry, cntry, 2); 61 | 62 | rtn= self; 63 | abort: 64 | return rtn; 65 | } 66 | 67 | OFFENTRY* 68 | OFFENTRY_cache_constructor(OFFENTRY *self, const char *cacheFileEntry) 69 | /******************************************************** 70 | * Prepare for use. 71 | */ 72 | { 73 | OFFENTRY *rtn= NULL; 74 | 75 | common_constructor(self); 76 | 77 | long long ll; 78 | 79 | int rc= sscanf(cacheFileEntry, "%u %u %lld %45s %2s" 80 | , &self->count 81 | , &self->severity 82 | , &ll 83 | , self->addr 84 | , self->cntry 85 | ); 86 | 87 | if(4 > rc) { 88 | eprintf("ERROR: failed to interpret \"%s\"", cacheFileEntry); 89 | goto abort; 90 | } 91 | 92 | self->latest= ll; 93 | 94 | #ifdef qqDEBUG 95 | if(self->severity) { 96 | eprintf("%s : %u", self->addr, self->severity); 97 | } 98 | #endif 99 | 100 | rtn= self; 101 | abort: 102 | return rtn; 103 | } 104 | 105 | void* 106 | OFFENTRY_destructor(OFFENTRY *self) 107 | /******************************************************** 108 | * Free resources. 109 | */ 110 | { 111 | if(self->dns.name) 112 | free(self->dns.name); 113 | 114 | return self; 115 | } 116 | 117 | void 118 | OFFENTRY_register(OFFENTRY *self, unsigned severity, time_t when) 119 | /******************************************************** 120 | * Register the current failure try. 121 | */ 122 | { 123 | /* Keep track of count */ 124 | ++self->count; 125 | 126 | #ifdef qqDEBUG 127 | if(severity) { 128 | eprintf("Severity= %u", severity); 129 | } 130 | #endif 131 | 132 | /* Keep track of most severe match */ 133 | if(self->severity < severity) 134 | self->severity= severity; 135 | 136 | /* Keep track of the most recent offense time */ 137 | if(self->latest < when) 138 | self->latest= when; 139 | 140 | } 141 | 142 | 143 | int 144 | OFFENTRY_cacheWrite(OFFENTRY *self, FILE *fh) 145 | /******************************************************** 146 | * Write to the cache file in a form we can read later. 147 | */ 148 | { 149 | ez_fprintf(fh, "%u %u %lld %s %s\n" 150 | , self->count 151 | , self->severity 152 | , (long long)self->latest 153 | , self->addr 154 | , self->cntry 155 | ); 156 | return 0; 157 | } 158 | 159 | int 160 | OFFENTRY_print(OFFENTRY *self, FILE *fh) 161 | /******************************************************** 162 | * Print a human readable representation of *self. 163 | */ 164 | { 165 | ez_fprintf(fh, 166 | "\tLOGENTRY %p { addr= \"%s\", cntry= \"%2s\" count= %u, severity= %u }\n" 167 | , self 168 | , self->addr 169 | , self->cntry 170 | , self->count 171 | , self->severity 172 | ); 173 | return 0; 174 | } 175 | 176 | int 177 | OFFENTRY_map_addr(OFFENTRY *self, MAP *h_rtnMap) 178 | /******************************************************** 179 | * Create a map of OFFENTRY objects with composite 180 | * counts by address. 181 | */ 182 | { 183 | OFFENTRY *e= MAP_findStrItem(h_rtnMap, self->addr); 184 | 185 | if(!e) { 186 | OFFENTRY_addr_create(e, self->addr); 187 | assert(e); 188 | MAP_addStrKey(h_rtnMap, e->addr, e); 189 | } 190 | 191 | e->count += self->count; 192 | 193 | if(e->severity < self->severity) 194 | e->severity= self->severity; 195 | 196 | if(e->latest < self->latest) 197 | e->latest= self->latest; 198 | return 0; 199 | } 200 | 201 | int 202 | OFFENTRY_offenseCount(OFFENTRY *self, unsigned *h_sum) 203 | /******************************************************** 204 | * Get a count of all offenses for this entry. 205 | */ 206 | { 207 | *h_sum += self->count; 208 | //eprintf("%s numItems= %u", self->addr, PTRVEC_numItems(&self->rptObj_vec)); 209 | return 0; 210 | } 211 | 212 | int 213 | OFFENTRY_list(OFFENTRY *self, FILE *fh, int flags, unsigned nAllowed) 214 | /******************************************************** 215 | * Print in listing form 216 | */ 217 | { 218 | static const struct bitTuple BlockBitTuples[]= { 219 | {.name= "BLK", .bit= BLOCKED_FLG}, 220 | {.name= "+blk+", .bit= WOULD_BLOCK_FLG}, 221 | {.name= "-blk-", .bit= UNJUST_BLOCK_FLG}, 222 | {.name= "WL", .bit= WHITELIST_FLG}, 223 | {/* Terminating member */} 224 | }; 225 | 226 | const static struct bitTuple dns_flagsArr[]= { 227 | {.name= "~", .bit= PDNS_FWD_FAIL_FLG}, 228 | {.name= "!", .bit= PDNS_FWD_MISMATCH_FLG}, 229 | {.name= "!!", .bit= PDNS_FWD_NONE_FLG}, 230 | {.name= "NXDOMAIN", .bit= PDNS_NXDOMAIN_FLG}, 231 | {.name= "SERVFAIL", .bit= PDNS_SERVFAIL_FLG}, 232 | {} 233 | }; 234 | 235 | 236 | #ifdef OLD 237 | const static char *dns_fmt= "%u %-13s %-15s\t%5u/%-4d offenses %s [%s] %s %s\n", 238 | *fmt= "%u %-13s %-15s\t%5u/%-4d offenses %s [%s]\n"; 239 | 240 | ez_fprintf(fh, self->dns.flags ? dns_fmt : fmt 241 | , self->severity 242 | , self->latest ? local_strftime(&self->latest, "%b %d %H:%M") : "" 243 | , self->addr 244 | , self->count 245 | , nAllowed 246 | , self->cntry[0] ? self->cntry : "--" 247 | , bits2str(flags, BlockBitTuples) 248 | , self->dns.name ? self->dns.name : "" 249 | , bits2str(self->dns.flags, dns_flagsArr) 250 | ); 251 | #else 252 | const static char *dns_fmt= "%u %-13s %5u/%-4d offenses %s [%-3s] %s \t%s %s\n", 253 | *fmt= "%u %-13s %5u/%-4d offenses %s [%-3s] %s\n"; 254 | 255 | ez_fprintf(fh, self->dns.flags ? dns_fmt : fmt 256 | , self->severity 257 | , self->latest ? local_strftime(&self->latest, "%b %d %H:%M") : "" 258 | , self->count 259 | , nAllowed 260 | , self->cntry[0] ? self->cntry : "--" 261 | , bits2str(flags, BlockBitTuples) 262 | , self->addr 263 | , self->dns.name ? self->dns.name : "" 264 | , bits2str(self->dns.flags, dns_flagsArr) 265 | ); 266 | #endif 267 | 268 | return 0; 269 | } 270 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | baseDir := ~ 2 | libsDir := $(baseDir)/libs 3 | projectName := ban2fail 4 | versions := debug release 5 | cc_exe := ban2fail b2f-grep 6 | #install_dir := /usr/local/bin 7 | 8 | ######################################## 9 | # Set up sources & libraries here. # 10 | ######################################## 11 | 12 | ifeq ($(exe), ban2fail) 13 | src := \ 14 | addrRpt.c \ 15 | ban2fail.c \ 16 | cfgmap.c \ 17 | cntry.c \ 18 | dynstack.c \ 19 | es.c \ 20 | ez_libc.c \ 21 | ez_libdb.c \ 22 | ez_libpthread.c \ 23 | ez_libz.c \ 24 | iptables.c \ 25 | logType.c \ 26 | logFile.c \ 27 | map.c \ 28 | maxoff.c \ 29 | msgqueue.c \ 30 | obsvTpl.c \ 31 | offEntry.c \ 32 | pdns.c \ 33 | ptrvec.c \ 34 | str.c \ 35 | target.c \ 36 | timestamp.c \ 37 | util.c \ 38 | 39 | libs += z crypto GeoIP pthread db 40 | endif 41 | 42 | ifeq ($(exe), b2f-grep) 43 | src := \ 44 | ez_libc.c \ 45 | b2f-grep.c \ 46 | ptrvec.c \ 47 | str.c \ 48 | util.c \ 49 | 50 | libs += gmp 51 | endif 52 | 53 | 54 | ifeq ($(exe), fsckdns) 55 | src := \ 56 | ez_libc.c \ 57 | fsckdns.c \ 58 | str.c \ 59 | util.c \ 60 | 61 | # libs := z crypto GeoIP pthread 62 | endif 63 | 64 | ######################################## 65 | # Set up custom compile flags here. # 66 | ######################################## 67 | ifeq ($(version),debug) 68 | local_cppflags := $(local_cppflags) -D_DEBUG -DDEBUG -std=gnu99 69 | local_codeflags := -g2 -O0 -Wreturn-type -Wformat -Wchar-subscripts -Wparentheses -Wcast-qual -Wmissing-declarations 70 | local_ldflags := $(local_ldflags) -L$(libsDir)/$(version) 71 | endif 72 | 73 | ifeq ($(version),release) 74 | local_cppflags := $(local_cppflags) -DNDEBUG -std=gnu99 75 | local_codeflags := -g0 -O3 -Wreturn-type -Wformat -Wchar-subscripts -Wparentheses -Wcast-qual -Wmissing-declarations 76 | local_ldflags := $(local_ldflags) -L$(libsDir)/$(version) 77 | endif 78 | 79 | makefile := Makefile 80 | ifndef version 81 | .PHONY : all clean tidy install uninstall debug release 82 | all : debug release 83 | debug : 84 | @$(MAKE) version=debug exe=ban2fail mainType=CC --no-builtin-rules -f $(makefile) --no-print-directory 85 | @$(MAKE) version=debug exe=b2f-grep mainType=CC --no-builtin-rules -f $(makefile) --no-print-directory 86 | release : 87 | @$(MAKE) version=release exe=ban2fail mainType=CC --no-builtin-rules -f $(makefile) --no-print-directory 88 | @$(MAKE) version=release exe=b2f-grep mainType=CC --no-builtin-rules -f $(makefile) --no-print-directory 89 | install : release 90 | @strip release/ban2fail 91 | @[ $(install_dir)_foo = _foo ] || cp release/ban2fail $(install_dir)/ 92 | @strip release/b2f-grep 93 | @[ $(install_dir)_foo = _foo ] || cp release/b2f-grep $(install_dir)/ 94 | @[ -e install.sh ] && INSTALLDIR=$(install_dir) INSTALLTYPE=$(install_type) sudo ./install.sh 95 | uninstall : 96 | clean : 97 | $(RM) -r $(versions) core *.bak *.tab.h *.tab.c *.yy.c *.yy.h 98 | tidy : 99 | $(RM) $(foreach vs, $(versions), $(vs)/*.o $(vs)/*.d) core *.bak 100 | endif 101 | .DELETE_ON_ERROR : 102 | 103 | ifdef version 104 | roots := \ 105 | $(patsubst %.cc, %, $(filter %.cc, $(src)))\ 106 | $(patsubst %.cxx, %, $(filter %.cxx, $(src)))\ 107 | $(patsubst %.cpp, %, $(filter %.cpp, $(src)))\ 108 | $(patsubst %.C, %, $(filter %.C, $(src)))\ 109 | $(patsubst %.c, %, $(filter %.c, $(src)))\ 110 | $(patsubst %.f, %, $(filter %.f, $(src)))\ 111 | $(patsubst %.for, %, $(filter %.for, $(src)))\ 112 | $(patsubst %.sal, %, $(filter %.sal, $(src)))\ 113 | $(patsubst %.asm, %, $(filter %.asm, $(src)))\ 114 | $(patsubst %.h, qt_%, $(filter %.h, $(src))) 115 | 116 | yacc_roots := $(patsubst %.y, %.tab, $(filter %.y, $(src))) 117 | lex_roots := $(patsubst %.l, %.yy, $(filter %.l, $(src))) 118 | obj := $(patsubst %, $(version)/%.o, $(roots) $(yacc_roots) $(lex_roots)) 119 | dep := $(patsubst %, $(version)/%.d, $(roots) $(yacc_roots) $(lex_roots)) 120 | 121 | 122 | ifdef exe #>>>>>>>>>>>> We are building an executable <<<<<<<<<<<<<<<< 123 | 124 | ifndef mainType 125 | $(version)/$(exe) : $(obj) 126 | @echo 'THE VARIABLE "mainType" MUST BE DEFINED TO: CXX or CC or FC' 127 | endif 128 | 129 | ifeq ($(mainType),CXX) 130 | $(version)/$(exe) : $(obj) 131 | $(CXX) $(LDFLAGS) $(local_ldflags) $(obj) $(patsubst %, -l%, $(libs)) -o $@ 132 | endif # ifeq CXX 133 | 134 | ifeq ($(mainType),CC) 135 | $(version)/$(exe) : $(obj) 136 | $(CC) $(LDFLAGS) $(local_ldflags) $(obj) $(patsubst %, -l%, $(libs)) -o $@ 137 | endif # ifeq CC 138 | 139 | ifeq ($(mainType),FC) 140 | $(version)/$(exe) : $(obj) 141 | $(FC) $(LDFLAGS) $(local_ldflags) $(obj) $(patsubst %, -l%, $(libs)) -o $@ 142 | endif # ifeq FC 143 | endif # ifdef exe 144 | 145 | 146 | ifdef library #>>>>>>>>>>>> We are building a library <<<<<<<<<<<<<<<< 147 | ifeq ($(libType),STATIC) 148 | ifdef libsDir 149 | $(libsDir)/$(version)/lib$(library).a : $(version)/lib$(library).a 150 | @[ -d $(libsDir)/$(version) ] || mkdir -p $(libsDir)/$(version) 151 | @ln -f -s `pwd`/$(version)/lib$(library).a $(libsDir)/$(version)/lib$(library).a 152 | 153 | endif # ifdef libsDir 154 | 155 | $(version)/lib$(library).a : $(obj) 156 | $(AR) $(ARFLAGS) $@ $(obj) 157 | endif # ifeq STATIC 158 | 159 | ifeq ($(libType),SHARED) 160 | ifdef libsDir 161 | $(libsDir)/$(version)/lib$(library) : $(version)/lib$(library) 162 | @[ -d $(libsDir)/$(version) ] || mkdir -p $(libsDir)/$(version) 163 | @ln -f -s `pwd`/$(version)/lib$(library) $(libsDir)/$(version)/lib$(library) 164 | 165 | endif # ifdef libsDir 166 | $(version)/lib$(library) : $(obj) 167 | g++ -shared -Wl,-soname,lib$(library) -o $@ $(obj) 168 | 169 | local_codeflags += -fno-strength-reduce -fPIC 170 | endif # ifeq SHARED 171 | 172 | endif # ifdef library 173 | #>>>>>>>>>>>>>>>>>>>> Finished library specific stuff <<<<<<<<<<<<<<<<< 174 | 175 | # yacc stuff 176 | yacc_h_output := $(patsubst %, %.h, $(yacc_roots)) 177 | yacc_c_output := $(patsubst %, %.c, $(yacc_roots)) 178 | yacc_output := $(yacc_h_output) $(yacc_c_output) 179 | 180 | %.tab.c : %.y 181 | bison -d $< 182 | %.tab.h : %.y 183 | bison -d $< 184 | 185 | # lex stuff 186 | lex_h_output := $(patsubst %, %.h, $(lex_roots)) 187 | lex_c_output := $(patsubst %, %.c, $(lex_roots)) 188 | lex_output := $(lex_h_output) $(lex_c_output) 189 | 190 | %.yy.c: %.l 191 | flex -o $*.yy.c --header-file=$*.yy.h $< 192 | %.yy.h: %.l 193 | flex -o $*.yy.c --header-file=$*.yy.h $< 194 | 195 | # Make sure the build directory exists 196 | $(dep) : | $(version) 197 | 198 | $(version) : 199 | @mkdir $(version) 200 | 201 | # Dependency files rule 202 | $(dep) : $(yacc_output) $(lex_output) 203 | 204 | # Recipes to build .d files 205 | $(version)/%.d: %.cc 206 | @set -e; $(CXX) -M $(CPPFLAGS) $(local_cppflags) $< \ 207 | | sed 's/\($*\)\.o[ :]*/$(version)\/\1.o $(version)\/\1.d : /' > $@ 208 | $(version)/%.d: %.cxx 209 | @set -e; $(CXX) -M $(CPPFLAGS) $(local_cppflags) $< \ 210 | | sed 's/\($*\)\.o[ :]*/$(version)\/\1.o $(version)\/\1.d : /' > $@ 211 | $(version)/%.d: %.cpp 212 | @set -e; $(CXX) -M $(CPPFLAGS) $(local_cppflags) $< \ 213 | | sed 's/\($*\)\.o[ :]*/$(version)\/\1.o $(version)\/\1.d : /' > $@ 214 | $(version)/%.d: %.C 215 | @set -e; $(CXX) -M $(CPPFLAGS) $(local_cppflags) $< \ 216 | | sed 's/\($*\)\.o[ :]*/$(version)\/\1.o $(version)\/\1.d : /' > $@ 217 | $(version)/%.d: %.c 218 | @set -e; $(CC) -M $(CPPFLAGS) $(local_cppflags) $< \ 219 | | sed 's/\($*\)\.o[ :]*/$(version)\/\1.o $(version)\/\1.d : /' > $@ 220 | 221 | $(version)/%.d: %.f 222 | @echo $(patsubst %.f, $(version)/%.o, $<) : $< > $@ 223 | 224 | $(version)/%.d: %.for 225 | @echo $(patsubst %.for, $(version)/%.o, $<) : $< > $@ 226 | 227 | $(version)/qt_%.d: %.h 228 | @echo $(patsubst %.h, $(version)/qt_%.cxx, $<) : $< > $@ 229 | 230 | $(version)/%.d: %.sal 231 | @echo $(patsubst %.sal, $(version)/%.s, $<) : $< > $@ 232 | 233 | $(version)/%.d: %.asm 234 | @echo $(patsubst %.asm, $(version)/%.s, $<) : $< > $@ 235 | 236 | # The .d files contain specific prerequisite dependencies 237 | -include $(patsubst %, $(version)/%.d, $(roots) $(yacc_roots) $(lex_roots)) 238 | 239 | # Recipes to build object files 240 | $(version)/%.o: %.cc 241 | $(CXX) -c $(CXXFLAGS) $(local_codeflags) $(CPPFLAGS) $(local_cppflags) $< -o $@ 242 | $(version)/%.o: %.cxx 243 | $(CXX) -c $(CXXFLAGS) $(local_codeflags) $(CPPFLAGS) $(local_cppflags) $< -o $@ 244 | $(version)/%.o: %.cpp 245 | $(CXX) -c $(CXXFLAGS) $(local_codeflags) $(CPPFLAGS) $(local_cppflags) $< -o $@ 246 | $(version)/%.o: %.C 247 | $(CXX) -c $(CXXFLAGS) $(local_codeflags) $(CPPFLAGS) $(local_cppflags) $< -o $@ 248 | $(version)/%.o: %.c 249 | $(CC) -c $(CCFLAGS) $(local_codeflags) $(CPPFLAGS) $(local_cppflags) $< -o $@ 250 | $(version)/%.o: %.f 251 | $(FC) -c $(FFLAGS) $(local_codeflags) $< -o $@ 252 | $(version)/%.o: %.for 253 | $(FC) -c $(FFLAGS) $(local_codeflags) $< -o $@ 254 | $(version)/qt_%.o: %.h 255 | $(QTDIR)/bin/moc $< -o $(version)/qt_$*.cxx 256 | $(CXX) -c $(CXXFLAGS) $(local_codeflags) $(CPPFLAGS) $(local_cppflags) $(version)/qt_$*.cxx -o $(version)/qt_$*.o 257 | 258 | endif # version 259 | -------------------------------------------------------------------------------- /cfgmap.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #ifndef CFGMAP_H 20 | #define CFGMAP_H 21 | #include 22 | #include 23 | 24 | #include "map.h" 25 | #include "ptrvec.h" 26 | #include "util.h" 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | /*===================== CFGMAP_ENTRY ========================*/ 33 | typedef struct { 34 | char *symbol; 35 | PTRVEC value_lst; /* Possible multiple values for a given symbol */ 36 | unsigned nLookups;/* How many times this symbol has been looked up */ 37 | unsigned symLen; 38 | } CFGMAP_ENTRY; 39 | 40 | unsigned int 41 | CFGMAP_ENTRY_numValues(const CFGMAP_ENTRY * self); 42 | /****************************************************************** 43 | * Return the number of values stored for a given entry. 44 | */ 45 | 46 | const char* 47 | CFGMAP_ENTRY_symbol(const CFGMAP_ENTRY * self); 48 | /****************************************************************** 49 | * Return the string for a the symbol. 50 | */ 51 | 52 | const char* 53 | CFGMAP_ENTRY_value(const CFGMAP_ENTRY * self, unsigned ndx); 54 | /****************************************************************** 55 | * Return the string for a the value indicated by ndx. 56 | */ 57 | 58 | const char* 59 | CFGMAP_ENTRY_value_sn(const CFGMAP_ENTRY * self, unsigned *sn_buf, unsigned ndx); 60 | /****************************************************************** 61 | * Return the string *and* serial number for a the value indicated by ndx. 62 | */ 63 | 64 | void 65 | CFGMAP_ENTRY_print(const CFGMAP_ENTRY * self, FILE * fh); 66 | /************************************************************************ 67 | * Print information for debugging. 68 | */ 69 | 70 | /*================== CFGMAP =================================*/ 71 | typedef struct { 72 | enum { 73 | CFGMAP_NTUPLES_KNOWN_FLG = 1 << 0 74 | } flags; 75 | unsigned recurs_lvl; 76 | MAP entry_map; /* Table of all entries in map */ 77 | PTRVEC curlyBlock_lst; /* Stack of curly brace block symbols */ 78 | unsigned serial_no_seq,/* For assigning serial number to values */ 79 | nTuples; 80 | } CFGMAP; 81 | 82 | #define CFGMAP_file_create(p, fname) \ 83 | (CFGMAP_file_constructor((p)=malloc(sizeof(CFGMAP)), fname) ? (p) : ( p ? realloc(CFGMAP_destructor(p),0) : 0 )) 84 | CFGMAP* 85 | CFGMAP_file_constructor(CFGMAP * self, const char *fname); 86 | /****************************************************************** 87 | * Create a map from a configuration file. 88 | */ 89 | 90 | #define CFGMAP_create(p) \ 91 | ((p)= (CFGMAP_constructor((p)=malloc(sizeof(CFGMAP))) ? (p) : ( p ? realloc(CFGMAP_destructor(p),0) : 0 ))) 92 | CFGMAP* 93 | CFGMAP_constructor(CFGMAP * self); 94 | /****************************************************************** 95 | * Create an empty map. 96 | */ 97 | 98 | #define CFGMAP_destroy(s) \ 99 | {if(CFGMAP_destructor(s)) {free(s); s=0;}} 100 | void* 101 | CFGMAP_destructor(CFGMAP * self); 102 | /****************************************************************** 103 | * Free resources associated with configuration file map. 104 | */ 105 | 106 | int 107 | CFGMAP_file_read(CFGMAP * self, const char *fname); 108 | /************************************************************************** 109 | * Read a file to populate the map. 110 | */ 111 | 112 | void 113 | CFGMAP_print(CFGMAP * self, FILE * fh); 114 | /****************************************************************** 115 | * Print to stream for debugging purposes 116 | */ 117 | 118 | int 119 | CFGMAP_visitAllSymbols(CFGMAP * self, int (*func) (const char *symbol, void *ctxt), void *ctxt); 120 | /****************************************************************** 121 | * Call (*func)() for all symbols in the map. 122 | */ 123 | 124 | size_t 125 | CFGMAP_numUnused_symbols(CFGMAP * self); 126 | /****************************************************************** 127 | * Print unused symbol count. 128 | */ 129 | 130 | void 131 | CFGMAP_print_unused_symbols(CFGMAP * self, FILE * fh); 132 | /****************************************************************** 133 | * Print unused symbols for troubleshooting 134 | */ 135 | 136 | const CFGMAP_ENTRY* 137 | CFGMAP_find(CFGMAP * self, const char *symbol); 138 | /************************************************************************ 139 | * Try to locate a matching CFGMAP_ENTRY 140 | */ 141 | 142 | struct CFGMAP_tuple { 143 | const char *key, 144 | *value; 145 | unsigned serial_no; 146 | }; 147 | 148 | unsigned 149 | CFGMAP_find_tuples(CFGMAP * self, struct CFGMAP_tuple rtn_arr[], const char *symbol); 150 | /************************************************************************ 151 | * Find all tuples with a key matching symbol 152 | * returns the number of tuples which were populated. 153 | */ 154 | 155 | int 156 | CFGMAP_regex_find(CFGMAP * self, const CFGMAP_ENTRY * rtn_arr[], const char *patternStr); 157 | /************************************************************************ 158 | * Find all instances of symbol which match patternStr. 159 | * Returns: the number of matches, or -1 for error. 160 | */ 161 | 162 | const char* 163 | CFGMAP_find_single_value(CFGMAP * self, const char *symbol); 164 | /************************************************************************ 165 | * Find exactly one value for a symbol, or return NULL. 166 | */ 167 | 168 | const char* 169 | CFGMAP_find_last_value(CFGMAP * self, const char *symbol); 170 | /************************************************************************ 171 | * Find the last value for a symbol, or return NULL. 172 | */ 173 | 174 | int 175 | CFGMAP_append(CFGMAP * self, const char *symbol, unsigned int symLen, const char *value); 176 | /************************************************************************** 177 | * Append a value to a config entry, creating a new entry if necessary. 178 | */ 179 | 180 | int 181 | CFGMAP_query_uint(CFGMAP * self, unsigned int *pRtn, unsigned int dfltVal, const char *symbol); 182 | /********************************************************************************** 183 | * Convenience query function. 184 | */ 185 | 186 | int 187 | CFGMAP_query_last_enum( 188 | CFGMAP * self, 189 | int *pRtn, 190 | int dfltVal, 191 | const char *symbol, 192 | const struct enumTuple et_arr[] 193 | ); 194 | /********************************************************************************** 195 | * Convenience query function for enums. 196 | */ 197 | 198 | int 199 | CFGMAP_query_last_flags( 200 | CFGMAP * self, 201 | int *pRtn, 202 | int dfltVal, 203 | const char *symbol, 204 | const struct bitTuple bt_arr[] 205 | ); 206 | /********************************************************************************** 207 | * Convenience query function for possibly OR'd flags. 208 | */ 209 | 210 | int 211 | CFGMAP_query_last_bool(CFGMAP * self, int *pRtn, int dfltVal, const char *symbol); 212 | /********************************************************************************** 213 | * Convenience function. 214 | */ 215 | 216 | int 217 | CFGMAP_query_last_int(CFGMAP * self, int *pRtn, int dfltVal, const char *symbol); 218 | /********************************************************************************** 219 | * Convenience function. 220 | */ 221 | 222 | int 223 | CFGMAP_query_last_uint(CFGMAP * self, unsigned *pRtn, unsigned dfltVal, const char *symbol); 224 | /********************************************************************************** 225 | * Convenience function. 226 | */ 227 | 228 | int 229 | CFGMAP_query_last_dbl(CFGMAP * self, double *pRtn, double dfltVal, const char *symbol); 230 | /********************************************************************************** 231 | * Convenience function. 232 | */ 233 | 234 | int 235 | CFGMAP_query_last_string(CFGMAP * self, char **pRtn, const char *dfltVal, const char *symbol); 236 | /********************************************************************************** 237 | * Convenience function. 238 | * Note: string assigned to *pRtn was allocated by strdup(). 239 | */ 240 | 241 | int 242 | CFGMAP_query_last_time_of_day(CFGMAP * self, int *pRtn, int dfltVal, const char *symbol); 243 | /********************************************************************************** 244 | * Convenience function to convert hh:mm to a number of seconds. 245 | */ 246 | 247 | unsigned int 248 | CFGMAP_numEntries(CFGMAP * self); 249 | /****************************************************************** 250 | * Return the number of values stored for a given entry. 251 | */ 252 | 253 | unsigned int 254 | CFGMAP_numTuples(CFGMAP * self); 255 | /****************************************************************** 256 | * Return the number of tuples stored in the configuration map. 257 | */ 258 | 259 | int 260 | CFGMAP_obtain_prefix(char *rtnBuf, size_t buf_sz, const char *path); 261 | /****************************************************************** 262 | * Given a full path string, place the prefix in rtnBuf. 263 | */ 264 | 265 | #ifdef __cplusplus 266 | } 267 | #endif 268 | #endif 269 | -------------------------------------------------------------------------------- /logFile.c: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2019 by John D. Robertson * 3 | * john@rrci.com * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 3 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * * 14 | * You should have received a copy of the GNU General Public License * 15 | * along with this program; if not, write to the * 16 | * Free Software Foundation, Inc., * 17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 18 | ***************************************************************************/ 19 | #define _GNU_SOURCE 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "addrRpt.h" 31 | #include "cntry.h" 32 | #include "dynstack.h" 33 | #include "ez_libc.h" 34 | #include "ez_libdb.h" 35 | #include "ez_libz.h" 36 | #include "logFile.h" 37 | #include "obsvTpl.h" 38 | #include "offEntry.h" 39 | #include "util.h" 40 | 41 | /*==================================================================*/ 42 | /*=================== LOGFILE ======================================*/ 43 | /*==================================================================*/ 44 | enum { 45 | NOFFENSES_CACHED_FLG =1<<0 46 | }; 47 | 48 | static void 49 | common_constructor(LOGFILE *self) 50 | /****************************************************************** 51 | * common portion for all constructors. 52 | */ 53 | { 54 | memset(self, 0, sizeof(*self)); 55 | MAP_constructor(&self->addr.offEntry_map, N_ADDRESSES_HINT/BUCKET_DEPTH_HINT, BUCKET_DEPTH_HINT); 56 | MAP_constructor(&self->addr.obsvTpl_map, N_ADDRESSES_HINT/BUCKET_DEPTH_HINT, BUCKET_DEPTH_HINT); 57 | } 58 | 59 | LOGFILE* 60 | LOGFILE_cache_constructor( 61 | LOGFILE *self, 62 | const char *cacheFname, 63 | const char *logFname 64 | ) 65 | /****************************************************************** 66 | * Initialize an instance of a LOGFILE class from a cache file. 67 | */ 68 | { 69 | LOGFILE *rtn= NULL; 70 | 71 | 72 | common_constructor(self); 73 | 74 | /* Not reentrant! */ 75 | gzFile log_fh= NULL; 76 | 77 | self->logFname= strdup(logFname); 78 | 79 | /* Open our database, if it exists */ 80 | DB *db= NULL; 81 | 82 | static char dbFname[PATH_MAX]; 83 | snprintf(dbFname, sizeof(dbFname), "%s.db", cacheFname); 84 | if(0 == ez_access(dbFname, F_OK)) { 85 | ez_db_create(&db, NULL, 0); 86 | ez_db_open(db, NULL, dbFname, NULL, DB_BTREE, DB_RDONLY, 0664); 87 | } 88 | 89 | /* Open the cache file */ 90 | FILE *cache_fh= ez_fopen(cacheFname, "r"); 91 | 92 | static char buf[256]; 93 | while(ez_fgets(buf, sizeof(buf), cache_fh)) { 94 | OFFENTRY *e; 95 | OFFENTRY_cache_create(e, buf); 96 | assert(e); 97 | MAP_addStrKey(&self->addr.offEntry_map, e->addr, e); 98 | 99 | AddrRPT *ar= MAP_findStrItem(&G.rpt.AddrRPT_map, e->addr); 100 | if(ar && db) { 101 | static ObsvTpl otpl; 102 | /* Initialize or reset static instance */ 103 | ObsvTpl_sinit(&otpl, self, e->addr); 104 | 105 | /* May not exist in database */ 106 | /* Fetch from database */ 107 | if(0 == ObsvTpl_db_get(&otpl, db)) { 108 | 109 | if(!log_fh) 110 | log_fh= ez_gzopen(logFname, "r"); 111 | 112 | /* Place observations in ar */ 113 | ObsvTpl_put_AddrRPT(&otpl, log_fh, ar); 114 | } 115 | } 116 | 117 | } 118 | 119 | rtn= self; 120 | 121 | abort: 122 | if(db) ez_db_close(db, 0); 123 | if(log_fh) ez_gzclose(log_fh); 124 | if(cache_fh) ez_fclose(cache_fh); 125 | return rtn; 126 | } 127 | 128 | LOGFILE* 129 | LOGFILE_log_constructor( 130 | LOGFILE *self, 131 | const struct logProtoType *h_protoType, 132 | const char *logFname 133 | ) 134 | /****************************************************************** 135 | * Initialize an instance of a LOGFILE from an actual log file. 136 | */ 137 | { 138 | LOGFILE *rtn= NULL; 139 | 140 | common_constructor(self); 141 | 142 | self->logFname= strdup(logFname); 143 | 144 | static char lbuf[1024]; 145 | 146 | /* Open the log file for reading */ 147 | gzFile gzfh= ez_gzopen(logFname, "r"); 148 | 149 | /* Loop through one line at a time */ 150 | while(gzfh) { 151 | z_off_t pos= ez_gztell(gzfh); 152 | if(!ez_gzgets(gzfh, lbuf, sizeof(lbuf)-1)) break; 153 | 154 | size_t line_len= strlen(lbuf); 155 | /* Get rid of trailing newline, spaces */ 156 | while(line_len && isspace(lbuf[line_len-1])) 157 | lbuf[--line_len]= '\0'; 158 | 159 | /* Search for a match in the targets */ 160 | for(Target *tg= h_protoType->targetArr; Target_is_init(tg); ++tg) { 161 | 162 | static char addr[128]; 163 | if(Target_scan(tg, addr, sizeof(addr), lbuf)) continue; 164 | 165 | OFFENTRY *e= MAP_findStrItem(&self->addr.offEntry_map, addr); 166 | if(!e) { 167 | OFFENTRY_addr_create(e, addr); 168 | if(!e) goto abort; 169 | 170 | /* Add to the addr.offEntry_map */ 171 | MAP_addStrKey(&self->addr.offEntry_map, e->addr, e); 172 | } 173 | 174 | /* See if we can extract the date */ 175 | time_t when= 0; 176 | if(TS_is_prepared(&h_protoType->ts)) { 177 | if(TS_scan(&h_protoType->ts, &when, lbuf, &G.begin.tm)) { 178 | eprintf("WARNING: TS_scan() failed."); 179 | } 180 | } 181 | 182 | OFFENTRY_register(e, Target_severity(tg), when); 183 | 184 | { /* Keep ObsvTpl record of offense line in log file */ 185 | ObsvTpl *ot= MAP_findStrItem(&self->addr.obsvTpl_map, e->addr); 186 | if(!ot) { 187 | ObsvTpl_create(ot, self, e->addr); 188 | assert(ot); 189 | MAP_addStrKey(&self->addr.obsvTpl_map, e->addr, ot); 190 | } 191 | 192 | ObsvTpl_addObsv(ot, pos, line_len); 193 | } 194 | } /* End of Target loop */ 195 | } /* End of line reading loop */ 196 | 197 | /* Take car of possible address reporting */ 198 | unsigned nItems= MAP_numItems(&G.rpt.AddrRPT_map); 199 | if(nItems) { /* Take care of address reports now */ 200 | AddrRPT *rtnArr[nItems]; 201 | MAP_fetchAllItems(&G.rpt.AddrRPT_map, (void**)rtnArr); 202 | for(unsigned i= 0; i < nItems; ++i) { 203 | AddrRPT *ar= rtnArr[i]; 204 | ObsvTpl *ot= MAP_findStrItem(&self->addr.obsvTpl_map, ar->addr); 205 | if(!ot) continue; 206 | ObsvTpl_put_AddrRPT(ot, gzfh, ar); 207 | } 208 | } 209 | 210 | rtn= self; 211 | abort: 212 | if(gzfh) ez_gzclose(gzfh); 213 | 214 | return rtn; 215 | } 216 | 217 | LOGFILE* 218 | LOGFILE_destructor(LOGFILE *self) 219 | /****************************************************************** 220 | * Free resources associated with LOGFILE object. 221 | */ 222 | { 223 | if(self->logFname) 224 | free(self->logFname); 225 | 226 | /* Clean up the maps and their contents */ 227 | MAP_clearAndDestroy(&self->addr.offEntry_map, (void*(*)(void*))OFFENTRY_destructor); 228 | MAP_destructor(&self->addr.offEntry_map); 229 | 230 | MAP_clearAndDestroy(&self->addr.obsvTpl_map, (void*(*)(void*))ObsvTpl_destructor); 231 | MAP_destructor(&self->addr.obsvTpl_map); 232 | 233 | return self; 234 | } 235 | 236 | int 237 | LOGFILE_writeCache(LOGFILE *self, const char *fname) 238 | /****************************************************************** 239 | * Create a cache file and dump contents of this object. 240 | */ 241 | { 242 | int rc, rtn= -1; 243 | DB *dbh= NULL; 244 | 245 | FILE *fh= ez_fopen(fname, "w"); 246 | ez_fchown(fileno(fh), getuid(), G.gid); 247 | ez_fchmod(fileno(fh), G.cache.file_mode); 248 | 249 | /* Writes all OFFENTRY object to fh */ 250 | rc= MAP_visitAllEntries(&self->addr.offEntry_map, (int(*)(void*,void*))OFFENTRY_cacheWrite, fh); 251 | if(rc) goto abort; 252 | 253 | 254 | /* Write RptObj's to database if any exist */ 255 | if(MAP_numItems(&self->addr.obsvTpl_map)) { 256 | 257 | static char dbFname[PATH_MAX]; 258 | snprintf(dbFname, sizeof(dbFname), "%s.db", fname); 259 | 260 | ez_db_create(&dbh, NULL, 0); 261 | assert(dbh); 262 | ez_db_open(dbh, NULL, dbFname, NULL, DB_BTREE, DB_CREATE, G.cache.file_mode); 263 | ez_chown(dbFname, getuid(), G.gid); 264 | 265 | /* This will write all entries in the map do the database */ 266 | MAP_visitAllEntries(&self->addr.obsvTpl_map, (int(*)(void*,void*))ObsvTpl_db_put, dbh); 267 | } 268 | 269 | rtn= 0; 270 | abort: 271 | if(dbh) ez_db_close(dbh, 0); 272 | if(fh) ez_fclose(fh); 273 | return rtn; 274 | } 275 | 276 | int 277 | LOGFILE_print(LOGFILE *self, FILE *fh) 278 | /******************************************************** 279 | * Print a human readable representation of *self. 280 | */ 281 | { 282 | ez_fprintf(fh, "LOGFILE %p \"%s\" {\n", self, self->logFname); 283 | MAP_visitAllEntries(&self->addr.offEntry_map, (int(*)(void*,void*))OFFENTRY_print, fh); 284 | ez_fprintf(fh, "}\n"); 285 | 286 | return 0; 287 | } 288 | 289 | int 290 | LOGFILE_map_addr(LOGFILE *self, MAP *h_rtnMap) 291 | /******************************************************** 292 | * Create a addr.offEntry_map of OFFENTRY objects with composite 293 | * counts by address. 294 | */ 295 | { 296 | MAP_visitAllEntries(&self->addr.offEntry_map, (int(*)(void*,void*))OFFENTRY_map_addr, h_rtnMap); 297 | return 0; 298 | } 299 | 300 | int 301 | LOGFILE_offenseCount(LOGFILE *self, unsigned *h_sum) 302 | /******************************************************** 303 | * Get a count of all offenses for this file. 304 | */ 305 | { 306 | if(!(self->flags & NOFFENSES_CACHED_FLG)) { 307 | MAP_visitAllEntries(&self->addr.offEntry_map, (int(*)(void*,void*))OFFENTRY_offenseCount, &self->nOffenses); 308 | self->flags |= NOFFENSES_CACHED_FLG; 309 | } 310 | 311 | *h_sum += self->nOffenses; 312 | 313 | return 0; 314 | } 315 | 316 | int 317 | LOGFILE_addressCount(LOGFILE *self, unsigned *h_sum) 318 | /******************************************************** 319 | * Get a count of all unique addresses for this file. 320 | */ 321 | { 322 | *h_sum += MAP_numItems(&self->addr.offEntry_map); 323 | return 0; 324 | } 325 | 326 | --------------------------------------------------------------------------------