mirror of https://github.com/jrbrtsn/ban2fail
Lots of new reporting features
This commit is contained in:
parent
bd5a01f5a2
commit
5549c4d188
|
@ -32,6 +32,8 @@ src := \
|
||||||
pdns.c \
|
pdns.c \
|
||||||
ptrvec.c \
|
ptrvec.c \
|
||||||
str.c \
|
str.c \
|
||||||
|
target.c \
|
||||||
|
timestamp.c \
|
||||||
util.c \
|
util.c \
|
||||||
|
|
||||||
libs := z crypto GeoIP pthread db
|
libs := z crypto GeoIP pthread db
|
||||||
|
|
128
ban2fail.c
128
ban2fail.c
|
@ -21,6 +21,7 @@
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "addrRpt.h"
|
#include "addrRpt.h"
|
||||||
|
@ -38,13 +39,6 @@
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
enum {
|
|
||||||
BLOCKED_FLG =1<<0,
|
|
||||||
WOULD_BLOCK_FLG =1<<1,
|
|
||||||
UNJUST_BLOCK_FLG =1<<2,
|
|
||||||
WHITELIST_FLG =1<<3
|
|
||||||
};
|
|
||||||
|
|
||||||
/*==================================================================*/
|
/*==================================================================*/
|
||||||
/*=================== Support structs ==============================*/
|
/*=================== Support structs ==============================*/
|
||||||
/*==================================================================*/
|
/*==================================================================*/
|
||||||
|
@ -67,6 +61,7 @@ static int addrRpt_serial_qsort(const void *p1, const void *p2);
|
||||||
static int cntryStat_count_qsort(const void *p1, const void *p2);
|
static int cntryStat_count_qsort(const void *p1, const void *p2);
|
||||||
static int configure(CFGMAP *h_cfgmap, const char *pfix);
|
static int configure(CFGMAP *h_cfgmap, const char *pfix);
|
||||||
static int logentry_count_qsort(const void *p1, const void *p2);
|
static int logentry_count_qsort(const void *p1, const void *p2);
|
||||||
|
static int logentry_latest_qsort(const void *p1, const void *p2);
|
||||||
static int map_byCountries(OFFENTRY *e, MAP *h_map);
|
static int map_byCountries(OFFENTRY *e, MAP *h_map);
|
||||||
static int stub_init(CFGMAP *map, char *symStr);
|
static int stub_init(CFGMAP *map, char *symStr);
|
||||||
|
|
||||||
|
@ -83,13 +78,21 @@ static const struct bitTuple GlobalFlagBitTuples[]= {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Global G= {
|
struct Global G= {
|
||||||
.cacheDir= CACHEDIR,
|
.cache= {
|
||||||
.lockDir= LOCKDIR,
|
.dir= CACHEDIR,
|
||||||
|
.dir_mode=0770,
|
||||||
|
.file_mode=0660
|
||||||
|
},
|
||||||
|
.lock= {
|
||||||
|
.dir= LOCKDIR,
|
||||||
|
.dir_mode= 0770,
|
||||||
|
.file_mode=0660
|
||||||
|
},
|
||||||
|
|
||||||
.version= {
|
.version= {
|
||||||
.major= 0,
|
.major= 0,
|
||||||
.minor= 13,
|
.minor= 13,
|
||||||
.patch= 3
|
.patch= 4
|
||||||
},
|
},
|
||||||
|
|
||||||
.bitTuples.flags= GlobalFlagBitTuples
|
.bitTuples.flags= GlobalFlagBitTuples
|
||||||
|
@ -101,14 +104,6 @@ const static struct initInfo S_initInfo_arr[] = {
|
||||||
{/* Terminating member */}
|
{/* Terminating member */}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct bitTuple BlockBitTuples[]= {
|
|
||||||
{.name= "BLK", .bit= BLOCKED_FLG},
|
|
||||||
{.name= "+blk+", .bit= WOULD_BLOCK_FLG},
|
|
||||||
{.name= "-blk-", .bit= UNJUST_BLOCK_FLG},
|
|
||||||
{.name= "WL", .bit= WHITELIST_FLG},
|
|
||||||
{/* Terminating member */}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*================ Local only static struct ======================*/
|
/*================ Local only static struct ======================*/
|
||||||
static struct {
|
static struct {
|
||||||
|
@ -169,6 +164,11 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
/* Prepare static data */
|
/* Prepare static data */
|
||||||
// global
|
// global
|
||||||
|
struct group *gr= ez_getgrnam(GROUP_NAME);
|
||||||
|
G.gid= gr->gr_gid;
|
||||||
|
|
||||||
|
/* Default sending listing to stdout */
|
||||||
|
G.rpt.fh= stdout;
|
||||||
MAP_constructor(&G.logType_map, 10, 10);
|
MAP_constructor(&G.logType_map, 10, 10);
|
||||||
MAP_constructor(&G.rpt.AddrRPT_map, 10, 10);
|
MAP_constructor(&G.rpt.AddrRPT_map, 10, 10);
|
||||||
|
|
||||||
|
@ -232,8 +232,8 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
G.flags |= GLB_DONT_IPTABLE_FLG;
|
G.flags |= GLB_DONT_IPTABLE_FLG;
|
||||||
G.cacheDir= CACHEDIR "-test";
|
G.cache.dir= CACHEDIR "-test";
|
||||||
G.lockDir= LOCKDIR "-test";
|
G.lock.dir= LOCKDIR "-test";
|
||||||
confFile= optarg;
|
confFile= optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -300,11 +300,13 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
} /* Done with command line arguments */
|
} /* Done with command line arguments */
|
||||||
|
|
||||||
/* Make sure we will be able to run iptables */
|
/* So we can run iptables */
|
||||||
if(getuid()) {
|
ez_setuid(0);
|
||||||
eprintf("ERROR: You must be root to run iptables!");
|
ez_setgid(G.gid);
|
||||||
goto abort;
|
|
||||||
}
|
/* Get a time when the scan began */
|
||||||
|
G.begin.time_t= time(NULL);
|
||||||
|
G.begin.tm= *localtime(&G.begin.time_t);
|
||||||
|
|
||||||
/* Read the configuration file */
|
/* Read the configuration file */
|
||||||
{ /*=========================================================*/
|
{ /*=========================================================*/
|
||||||
|
@ -313,6 +315,9 @@ main(int argc, char **argv)
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For debugging this can be useful */
|
||||||
|
// CFGMAP_print(&S.cfgmap, G.rpt.fh);
|
||||||
|
|
||||||
/* Just leave the S.cfgmap in place, so all the value strings
|
/* Just leave the S.cfgmap in place, so all the value strings
|
||||||
* don't need to be copied.
|
* don't need to be copied.
|
||||||
*/
|
*/
|
||||||
|
@ -321,21 +326,21 @@ main(int argc, char **argv)
|
||||||
/* Obtain a file lock to protect cache files */
|
/* Obtain a file lock to protect cache files */
|
||||||
/*===========================================================*/
|
/*===========================================================*/
|
||||||
{
|
{
|
||||||
if(-1 == ez_access(G.lockDir, F_OK))
|
if(-1 == ez_access(G.lock.dir, F_OK)) {
|
||||||
ez_mkdir(G.lockDir, 0750);
|
ez_mkdir(G.lock.dir, G.lock.dir_mode);
|
||||||
|
ez_chown(G.lock.dir, getuid(), G.gid);
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(S.fnameBuf, sizeof(S.fnameBuf), "%s/cache", G.lockDir);
|
snprintf(S.fnameBuf, sizeof(S.fnameBuf), "%s/cache", G.lock.dir);
|
||||||
/* Make sure the file exists by open()'ing */
|
/* Make sure the file exists by open()'ing */
|
||||||
S.cacheLock_fd= ez_open(S.fnameBuf, O_CREAT|O_WRONLY|O_CLOEXEC, 0640);
|
S.cacheLock_fd= ez_open(S.fnameBuf, O_CREAT|O_RDONLY|O_CLOEXEC, G.lock.file_mode);
|
||||||
assert(-1 != S.cacheLock_fd);
|
ez_fchown(S.cacheLock_fd, getuid(), G.gid);
|
||||||
|
|
||||||
/* Let's get a exclusive lock */
|
/* Let's get a exclusive lock */
|
||||||
// TODO: set SIGALRM to knock us out of blocked wait?
|
// TODO: set SIGALRM to knock us out of blocked wait?
|
||||||
int rc= ez_flock(S.cacheLock_fd, LOCK_EX);
|
int rc= ez_flock(S.cacheLock_fd, LOCK_EX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default sending listing to stdout */
|
|
||||||
G.rpt.fh= stdout;
|
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
/* if stdout is a tty, and listing is likely
|
/* if stdout is a tty, and listing is likely
|
||||||
* to be long, then use $PAGER.
|
* to be long, then use $PAGER.
|
||||||
|
@ -349,16 +354,19 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
/* Open our cache, instance file-specific LOGTYPE objects */
|
/* Open our cache, instance file-specific LOGTYPE objects */
|
||||||
{ /*=============================================================*/
|
{ /*=============================================================*/
|
||||||
if(G.flags & GLB_FLUSH_CACHE_FLG && !access(G.cacheDir, F_OK)) {
|
if(G.flags & GLB_FLUSH_CACHE_FLG &&
|
||||||
ez_rmdir_recursive(G.cacheDir);
|
!ez_access(G.cache.dir, F_OK))
|
||||||
|
{
|
||||||
|
ez_rmdir_recursive(G.cache.dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the directory if needed */
|
/* Make the directory if needed */
|
||||||
if(access(G.cacheDir, F_OK)) {
|
if(ez_access(G.cache.dir, F_OK)) {
|
||||||
/* errno will be set if access() fails */
|
/* errno will be set if access() fails */
|
||||||
errno= 0;
|
errno= 0;
|
||||||
|
|
||||||
ez_mkdir(G.cacheDir, 0750);
|
ez_mkdir(G.cache.dir, G.cache.dir_mode);
|
||||||
|
ez_chown(G.cache.dir, getuid(), G.gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(G.flags & GLB_LONG_LISTING_MASK) {
|
if(G.flags & GLB_LONG_LISTING_MASK) {
|
||||||
|
@ -398,7 +406,7 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
/* Check cache for logType directories not in our current map, and remove them */
|
/* Check cache for logType directories not in our current map, and remove them */
|
||||||
{ /*---------------------------------------------------------------------*/
|
{ /*---------------------------------------------------------------------*/
|
||||||
DIR *dir= ez_opendir(G.cacheDir);
|
DIR *dir= ez_opendir(G.cache.dir);
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
|
|
||||||
while((entry= ez_readdir(dir))) {
|
while((entry= ez_readdir(dir))) {
|
||||||
|
@ -412,7 +420,7 @@ main(int argc, char **argv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Make the path with filename */
|
/* Make the path with filename */
|
||||||
snprintf(S.fnameBuf, sizeof(S.fnameBuf), "%s/%s", G.cacheDir, entry->d_name);
|
snprintf(S.fnameBuf, sizeof(S.fnameBuf), "%s/%s", G.cache.dir, entry->d_name);
|
||||||
|
|
||||||
/* Remove unused directory & contents. */
|
/* Remove unused directory & contents. */
|
||||||
ez_rmdir_recursive(S.fnameBuf);
|
ez_rmdir_recursive(S.fnameBuf);
|
||||||
|
@ -475,7 +483,7 @@ main(int argc, char **argv)
|
||||||
assert(S.lePtrArr);
|
assert(S.lePtrArr);
|
||||||
|
|
||||||
MAP_fetchAllItems(&S.addr2logEntry_map, (void**)S.lePtrArr);
|
MAP_fetchAllItems(&S.addr2logEntry_map, (void**)S.lePtrArr);
|
||||||
qsort(S.lePtrArr, nItems, sizeof(OFFENTRY*), logentry_count_qsort);
|
qsort(S.lePtrArr, nItems, sizeof(OFFENTRY*), logentry_latest_qsort);
|
||||||
|
|
||||||
/* Special processing for DNS lookups */
|
/* Special processing for DNS lookups */
|
||||||
if(G.flags & GLB_DNS_LOOKUP_FLG) {
|
if(G.flags & GLB_DNS_LOOKUP_FLG) {
|
||||||
|
@ -525,27 +533,7 @@ main(int argc, char **argv)
|
||||||
if(G.flags & GLB_LIST_ADDR_FLG &&
|
if(G.flags & GLB_LIST_ADDR_FLG &&
|
||||||
!(G.flags & GLB_DNS_FILTER_BAD_FLG && e->dns.flags & PDNS_BAD_MASK))
|
!(G.flags & GLB_DNS_FILTER_BAD_FLG && e->dns.flags & PDNS_BAD_MASK))
|
||||||
{
|
{
|
||||||
|
OFFENTRY_list(e, G.rpt.fh, flags, nAllowed);
|
||||||
const static struct bitTuple dns_flagsArr[]= {
|
|
||||||
{.name= "~", .bit= PDNS_FWD_FAIL_FLG},
|
|
||||||
{.name= "!!", .bit= PDNS_FWD_NONE_FLG},
|
|
||||||
{.name= "NXDOMAIN", .bit= PDNS_NXDOMAIN_FLG},
|
|
||||||
{.name= "SERVFAIL", .bit= PDNS_SERVFAIL_FLG},
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
const static char *dns_fmt= "%-15s\t%5u/%-4d offenses %s [%s] %s %s\n",
|
|
||||||
*fmt= "%-15s\t%5u/%-4d offenses %s [%s]\n";
|
|
||||||
|
|
||||||
ez_fprintf(G.rpt.fh, e->dns.flags ? dns_fmt : fmt
|
|
||||||
, e->addr
|
|
||||||
, e->count
|
|
||||||
, nAllowed
|
|
||||||
, e->cntry[0] ? e->cntry : "--"
|
|
||||||
, bits2str(flags, BlockBitTuples)
|
|
||||||
, e->dns.name ? e->dns.name : ""
|
|
||||||
, bits2str(e->dns.flags, dns_flagsArr)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} /*--- End of OFFENTRY processing ---*/
|
} /*--- End of OFFENTRY processing ---*/
|
||||||
|
@ -599,10 +587,10 @@ main(int argc, char **argv)
|
||||||
if(!(G.flags & GLB_DONT_IPTABLE_FLG)) {
|
if(!(G.flags & GLB_DONT_IPTABLE_FLG)) {
|
||||||
|
|
||||||
if(n2Block || n2Unblock) {
|
if(n2Block || n2Unblock) {
|
||||||
snprintf(S.fnameBuf, sizeof(S.fnameBuf), "%s/iptables", G.lockDir);
|
snprintf(S.fnameBuf, sizeof(S.fnameBuf), "%s/iptables", G.lock.dir);
|
||||||
/* Make sure the file exists by open()'ing */
|
/* Make sure the file exists by open()'ing */
|
||||||
S.iptablesLock_fd= ez_open(S.fnameBuf, O_CREAT|O_WRONLY|O_CLOEXEC, 0640);
|
S.iptablesLock_fd= ez_open(S.fnameBuf, O_CREAT|O_WRONLY|O_CLOEXEC, G.lock.file_mode);
|
||||||
assert(-1 != S.iptablesLock_fd);
|
ez_fchown(S.iptablesLock_fd, getuid(), G.gid);
|
||||||
/* Get an exclusive lock on the lockfile */
|
/* Get an exclusive lock on the lockfile */
|
||||||
ez_flock(S.iptablesLock_fd, LOCK_EX);
|
ez_flock(S.iptablesLock_fd, LOCK_EX);
|
||||||
}
|
}
|
||||||
|
@ -684,6 +672,20 @@ abort:
|
||||||
/*==================================================================*/
|
/*==================================================================*/
|
||||||
/*============== Supporting functions ==============================*/
|
/*============== Supporting functions ==============================*/
|
||||||
/*==================================================================*/
|
/*==================================================================*/
|
||||||
|
static int
|
||||||
|
logentry_latest_qsort(const void *p1, const void *p2)
|
||||||
|
/***************************************************************
|
||||||
|
* qsort functor puts large counts on top.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
const OFFENTRY *le1= *(const OFFENTRY *const*)p1,
|
||||||
|
*le2= *(const OFFENTRY *const*)p2;
|
||||||
|
|
||||||
|
if(le1->latest > le2->latest) return -1;
|
||||||
|
if(le1->latest < le2->latest) return 1;
|
||||||
|
return logentry_count_qsort(p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
logentry_count_qsort(const void *p1, const void *p2)
|
logentry_count_qsort(const void *p1, const void *p2)
|
||||||
|
|
32
ban2fail.h
32
ban2fail.h
|
@ -26,6 +26,8 @@
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "cfgmap.h"
|
#include "cfgmap.h"
|
||||||
|
|
||||||
|
@ -59,6 +61,7 @@
|
||||||
#define IP6TABLES "/usr/sbin/ip6tables"
|
#define IP6TABLES "/usr/sbin/ip6tables"
|
||||||
#define GEOIP_DB "/usr/share/GeoIP/GeoIP.dat"
|
#define GEOIP_DB "/usr/share/GeoIP/GeoIP.dat"
|
||||||
#define GEOIP6_DB "/usr/share/GeoIP/GeoIPv6.dat"
|
#define GEOIP6_DB "/usr/share/GeoIP/GeoIPv6.dat"
|
||||||
|
#define GROUP_NAME "adm"
|
||||||
|
|
||||||
enum GlobalFlg_enum {
|
enum GlobalFlg_enum {
|
||||||
GLB_VERBOSE_FLG =1<<0,
|
GLB_VERBOSE_FLG =1<<0,
|
||||||
|
@ -74,6 +77,13 @@ enum GlobalFlg_enum {
|
||||||
GLB_LONG_LISTING_MASK = GLB_LIST_CNTRY_FLG|GLB_LIST_ADDR_FLG
|
GLB_LONG_LISTING_MASK = GLB_LIST_CNTRY_FLG|GLB_LIST_ADDR_FLG
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum BlockedFlg_enum {
|
||||||
|
BLOCKED_FLG =1<<0,
|
||||||
|
WOULD_BLOCK_FLG =1<<1,
|
||||||
|
UNJUST_BLOCK_FLG =1<<2,
|
||||||
|
WHITELIST_FLG =1<<3
|
||||||
|
};
|
||||||
|
|
||||||
/* Singleton static object with global visibility */
|
/* Singleton static object with global visibility */
|
||||||
extern struct Global {
|
extern struct Global {
|
||||||
|
|
||||||
|
@ -81,8 +91,21 @@ extern struct Global {
|
||||||
|
|
||||||
MAP logType_map;
|
MAP logType_map;
|
||||||
|
|
||||||
char *cacheDir,
|
struct {
|
||||||
*lockDir;
|
char *dir;
|
||||||
|
mode_t dir_mode,
|
||||||
|
file_mode;
|
||||||
|
} cache;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *dir;
|
||||||
|
mode_t dir_mode,
|
||||||
|
file_mode;
|
||||||
|
} lock;
|
||||||
|
|
||||||
|
/* This should be set to adm */
|
||||||
|
gid_t gid;
|
||||||
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
FILE *fh;
|
FILE *fh;
|
||||||
|
@ -99,6 +122,11 @@ extern struct Global {
|
||||||
const struct bitTuple *flags;
|
const struct bitTuple *flags;
|
||||||
} bitTuples;
|
} bitTuples;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
time_t time_t;
|
||||||
|
struct tm tm;
|
||||||
|
} begin;
|
||||||
|
|
||||||
} G;
|
} G;
|
||||||
|
|
||||||
|
|
||||||
|
|
160
ez_libc.c
160
ez_libc.c
|
@ -92,8 +92,9 @@ FILE* _ez_popen (
|
||||||
const char *type
|
const char *type
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
errno= 0;
|
||||||
FILE *rtn= popen (command, type);
|
FILE *rtn= popen (command, type);
|
||||||
if (!rtn) {
|
if (!rtn || errno) {
|
||||||
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "popen(\"%s\", \"%s\") failed", command, type);
|
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "popen(\"%s\", \"%s\") failed", command, type);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -524,6 +525,7 @@ int _ez_open(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
int _ez_access(
|
int _ez_access(
|
||||||
const char *fileName,
|
const char *fileName,
|
||||||
int lineNo,
|
int lineNo,
|
||||||
|
@ -547,3 +549,159 @@ int _ez_access(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
|
char *_ez_strptime(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
const char *s,
|
||||||
|
const char *format,
|
||||||
|
struct tm *tm
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char *rtn= strptime (s, format, tm);
|
||||||
|
if(rtn) return rtn;
|
||||||
|
|
||||||
|
_eprintf(fileName, lineNo, funcName, "strptime(\"%s\",\"%s\") failed", s, format);
|
||||||
|
abort();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
|
int _ez_seteuid(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
uid_t euid
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rtn= seteuid (euid);
|
||||||
|
if(0 == rtn) return 0;
|
||||||
|
|
||||||
|
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "seteuid(%d) failed", (int)euid);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
|
int _ez_setegid(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
gid_t egid
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rtn= setegid (egid);
|
||||||
|
if(0 == rtn) return 0;
|
||||||
|
|
||||||
|
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "setegid(%d) failed", (int)egid);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
|
struct group* _ez_getgrnam(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
const char *name
|
||||||
|
)
|
||||||
|
{
|
||||||
|
errno= 0;
|
||||||
|
struct group *rtn= getgrnam (name);
|
||||||
|
|
||||||
|
if(rtn) return rtn;
|
||||||
|
|
||||||
|
switch(errno) {
|
||||||
|
case EINTR:
|
||||||
|
case EIO:
|
||||||
|
case EMFILE:
|
||||||
|
case ENFILE:
|
||||||
|
case ENOMEM:
|
||||||
|
case ERANGE:
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "getgrnam(\"%s\") failed", name);
|
||||||
|
abort();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
|
int _ez_chown(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
const char *pathname,
|
||||||
|
uid_t owner,
|
||||||
|
gid_t group
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rtn= chown (pathname, owner, group);
|
||||||
|
if(0 == rtn) return rtn;
|
||||||
|
|
||||||
|
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "chown(\"%s\", %d, %d) failed", pathname, (int)owner, (int)group);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
|
int _ez_fchown(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
int fd,
|
||||||
|
uid_t owner,
|
||||||
|
gid_t group
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rtn= fchown (fd, owner, group);
|
||||||
|
if(0 == rtn) return rtn;
|
||||||
|
|
||||||
|
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "fchown() failed");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
|
int _ez_fchmod(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
int fd,
|
||||||
|
mode_t mode
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rtn= fchmod (fd, mode);
|
||||||
|
if(0 == rtn) return rtn;
|
||||||
|
|
||||||
|
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "fchmod() failed");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
|
int _ez_setuid(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
uid_t uid
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rtn= setuid (uid);
|
||||||
|
if(0 == rtn) return 0;
|
||||||
|
|
||||||
|
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "setuid(%d) failed", (int)uid);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
|
int _ez_setgid(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
gid_t gid
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rtn= setgid (gid);
|
||||||
|
if(0 == rtn) return 0;
|
||||||
|
|
||||||
|
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "setgid(%d) failed", (int)gid);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
90
ez_libc.h
90
ez_libc.h
|
@ -30,17 +30,30 @@ glibc calls with boilerplate error handling.
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <grp.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ez_strptime(s, format, tm) \
|
||||||
|
_ez_strptime(__FILE__, __LINE__, __FUNCTION__, s, format, tm)
|
||||||
|
char *_ez_strptime(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
const char *s,
|
||||||
|
const char *format,
|
||||||
|
struct tm *tm
|
||||||
|
);
|
||||||
|
|
||||||
#define ez_access(pathname, mode) \
|
#define ez_access(pathname, mode) \
|
||||||
_ez_access(__FILE__, __LINE__, __FUNCTION__, pathname, mode)
|
_ez_access(__FILE__, __LINE__, __FUNCTION__, pathname, mode)
|
||||||
int _ez_access(
|
int _ez_access(
|
||||||
|
@ -341,6 +354,83 @@ int _ez_flock (
|
||||||
int operation
|
int operation
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#define ez_setuid(uid) \
|
||||||
|
_ez_setuid(__FILE__, __LINE__, __FUNCTION__, uid)
|
||||||
|
int _ez_setuid(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
uid_t uid
|
||||||
|
);
|
||||||
|
|
||||||
|
#define ez_setgid(gid) \
|
||||||
|
_ez_setgid(__FILE__, __LINE__, __FUNCTION__, gid)
|
||||||
|
int _ez_setgid(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
gid_t gid
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
#define ez_seteuid(euid) \
|
||||||
|
_ez_seteuid(__FILE__, __LINE__, __FUNCTION__, euid)
|
||||||
|
int _ez_seteuid(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
uid_t euid
|
||||||
|
);
|
||||||
|
|
||||||
|
#define ez_setegid(egid) \
|
||||||
|
_ez_setegid(__FILE__, __LINE__, __FUNCTION__, egid)
|
||||||
|
int _ez_setegid(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
gid_t egid
|
||||||
|
);
|
||||||
|
|
||||||
|
#define ez_getgrnam(name) \
|
||||||
|
_ez_getgrnam(__FILE__, __LINE__, __FUNCTION__, name)
|
||||||
|
struct group* _ez_getgrnam(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
const char *name
|
||||||
|
);
|
||||||
|
|
||||||
|
#define ez_chown(pathname, owner, group) \
|
||||||
|
_ez_chown(__FILE__, __LINE__, __FUNCTION__, pathname, owner, group)
|
||||||
|
int _ez_chown(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
const char *pathname,
|
||||||
|
uid_t owner,
|
||||||
|
gid_t group
|
||||||
|
);
|
||||||
|
|
||||||
|
#define ez_fchown(fd, owner, group) \
|
||||||
|
_ez_fchown(__FILE__, __LINE__, __FUNCTION__, fd, owner, group)
|
||||||
|
int _ez_fchown(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
int fd,
|
||||||
|
uid_t owner,
|
||||||
|
gid_t group
|
||||||
|
);
|
||||||
|
|
||||||
|
#define ez_fchmod(fd, mode) \
|
||||||
|
_ez_fchmod(__FILE__, __LINE__, __FUNCTION__, fd, mode)
|
||||||
|
int _ez_fchmod(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
int fd,
|
||||||
|
mode_t mode
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
20
ez_libdb.c
20
ez_libdb.c
|
@ -145,7 +145,6 @@ int _ez_db_close(
|
||||||
u_int32_t flags
|
u_int32_t flags
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
//eprintf("Closing database (%p)", db);
|
|
||||||
int rtn= db->close(db, flags);
|
int rtn= db->close(db, flags);
|
||||||
|
|
||||||
if(!rtn) return 0;
|
if(!rtn) return 0;
|
||||||
|
@ -155,3 +154,22 @@ int _ez_db_close(
|
||||||
_sys_eprintf((const char*(*)(int))db_strerror, fileName, lineNo, funcName, "DB->close() failed");
|
_sys_eprintf((const char*(*)(int))db_strerror, fileName, lineNo, funcName, "DB->close() failed");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************/
|
||||||
|
int _ez_db_fd(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
DB *db,
|
||||||
|
int *fdp
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int rtn= db->fd(db, fdp);
|
||||||
|
|
||||||
|
if(!rtn) return 0;
|
||||||
|
|
||||||
|
/* _sys_eprintf() will pass errno to db_sterror */
|
||||||
|
errno= rtn;
|
||||||
|
_sys_eprintf((const char*(*)(int))db_strerror, fileName, lineNo, funcName, "DB->fd() failed");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
10
ez_libdb.h
10
ez_libdb.h
|
@ -101,6 +101,16 @@ int _ez_db_close(
|
||||||
u_int32_t flags
|
u_int32_t flags
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#define ez_db_fd(db, fdp) \
|
||||||
|
_ez_db_fd(__FILE__, __LINE__, __FUNCTION__, db, fdp)
|
||||||
|
int _ez_db_fd(
|
||||||
|
const char *fileName,
|
||||||
|
int lineNo,
|
||||||
|
const char *funcName,
|
||||||
|
DB *db,
|
||||||
|
int *fdp
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
10
iptables.c
10
iptables.c
|
@ -76,7 +76,9 @@ initialize (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
fh= ez_popen(ipv->cmd, "r");
|
fh= ez_popen(ipv->cmd, "r");
|
||||||
|
#ifdef qqDEBUG
|
||||||
|
unsigned count= 0;
|
||||||
|
#endif
|
||||||
while(ez_fgets(lbuf, sizeof(lbuf)-1, fh)) {
|
while(ez_fgets(lbuf, sizeof(lbuf)-1, fh)) {
|
||||||
|
|
||||||
/* Filter all that looks uninteresting */
|
/* Filter all that looks uninteresting */
|
||||||
|
@ -93,9 +95,15 @@ initialize (void)
|
||||||
eprintf("WARNING: duplicate iptable entry for %s", addr);
|
eprintf("WARNING: duplicate iptable entry for %s", addr);
|
||||||
else
|
else
|
||||||
MAP_addStrKey(&S.addr_map, addr, strdup(addr));
|
MAP_addStrKey(&S.addr_map, addr, strdup(addr));
|
||||||
|
#ifdef qqDEBUG
|
||||||
|
++count;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
ez_pclose(fh);
|
ez_pclose(fh);
|
||||||
regfree(&re);
|
regfree(&re);
|
||||||
|
#ifdef qqDEBUG
|
||||||
|
eprintf("%s got %u entries", ipv->cmd, count);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
32
logFile.c
32
logFile.c
|
@ -81,7 +81,7 @@ LOGFILE_cache_constructor(
|
||||||
|
|
||||||
static char dbFname[PATH_MAX];
|
static char dbFname[PATH_MAX];
|
||||||
snprintf(dbFname, sizeof(dbFname), "%s.db", cacheFname);
|
snprintf(dbFname, sizeof(dbFname), "%s.db", cacheFname);
|
||||||
if(0 == access(dbFname, F_OK)) {
|
if(0 == ez_access(dbFname, F_OK)) {
|
||||||
ez_db_create(&db, NULL, 0);
|
ez_db_create(&db, NULL, 0);
|
||||||
ez_db_open(db, NULL, dbFname, NULL, DB_BTREE, DB_RDONLY, 0664);
|
ez_db_open(db, NULL, dbFname, NULL, DB_BTREE, DB_RDONLY, 0664);
|
||||||
}
|
}
|
||||||
|
@ -157,18 +157,10 @@ LOGFILE_log_constructor(
|
||||||
lbuf[--line_len]= '\0';
|
lbuf[--line_len]= '\0';
|
||||||
|
|
||||||
/* Search for a match in the targets */
|
/* Search for a match in the targets */
|
||||||
for(struct target *tg= h_protoType->targetArr; tg->pattern; ++tg) {
|
for(Target *tg= h_protoType->targetArr; Target_is_init(tg); ++tg) {
|
||||||
|
|
||||||
/* If there is no match, continue looking */
|
|
||||||
regmatch_t matchArr[2];
|
|
||||||
if(0 != regexec(&tg->re, lbuf, 2, matchArr, 0) || -1 == matchArr[1].rm_so)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
static char addr[128];
|
static char addr[128];
|
||||||
unsigned len;
|
if(Target_scan(tg, addr, sizeof(addr), lbuf)) continue;
|
||||||
len= matchArr[1].rm_eo - matchArr[1].rm_so;
|
|
||||||
strncpy(addr, lbuf+matchArr[1].rm_so, sizeof(addr)-1);
|
|
||||||
addr[MIN(len, sizeof(addr)-1)]= '\0';
|
|
||||||
|
|
||||||
OFFENTRY *e= MAP_findStrItem(&self->addr.offEntry_map, addr);
|
OFFENTRY *e= MAP_findStrItem(&self->addr.offEntry_map, addr);
|
||||||
if(!e) {
|
if(!e) {
|
||||||
|
@ -179,7 +171,15 @@ LOGFILE_log_constructor(
|
||||||
MAP_addStrKey(&self->addr.offEntry_map, e->addr, e);
|
MAP_addStrKey(&self->addr.offEntry_map, e->addr, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
OFFENTRY_register(e);
|
/* See if we can extract the date */
|
||||||
|
time_t when= 0;
|
||||||
|
if(TS_is_prepared(&h_protoType->ts)) {
|
||||||
|
if(TS_scan(&h_protoType->ts, &when, lbuf, &G.begin.tm)) {
|
||||||
|
eprintf("WARNING: TS_scan() failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OFFENTRY_register(e, Target_severity(tg), when);
|
||||||
|
|
||||||
{ /* Keep ObsvTpl record of offense line in log file */
|
{ /* Keep ObsvTpl record of offense line in log file */
|
||||||
ObsvTpl *ot= MAP_findStrItem(&self->addr.obsvTpl_map, e->addr);
|
ObsvTpl *ot= MAP_findStrItem(&self->addr.obsvTpl_map, e->addr);
|
||||||
|
@ -190,9 +190,8 @@ LOGFILE_log_constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
ObsvTpl_addObsv(ot, pos, line_len);
|
ObsvTpl_addObsv(ot, pos, line_len);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
} /* End of Target loop */
|
||||||
} /* End of line reading loop */
|
} /* End of line reading loop */
|
||||||
|
|
||||||
/* Take car of possible address reporting */
|
/* Take car of possible address reporting */
|
||||||
|
@ -244,6 +243,8 @@ LOGFILE_writeCache(LOGFILE *self, const char *fname)
|
||||||
DB *dbh= NULL;
|
DB *dbh= NULL;
|
||||||
|
|
||||||
FILE *fh= ez_fopen(fname, "w");
|
FILE *fh= ez_fopen(fname, "w");
|
||||||
|
ez_fchown(fileno(fh), getuid(), G.gid);
|
||||||
|
ez_fchmod(fileno(fh), G.cache.file_mode);
|
||||||
|
|
||||||
/* Writes all OFFENTRY object to fh */
|
/* Writes all OFFENTRY object to fh */
|
||||||
rc= MAP_visitAllEntries(&self->addr.offEntry_map, (int(*)(void*,void*))OFFENTRY_cacheWrite, fh);
|
rc= MAP_visitAllEntries(&self->addr.offEntry_map, (int(*)(void*,void*))OFFENTRY_cacheWrite, fh);
|
||||||
|
@ -258,7 +259,8 @@ LOGFILE_writeCache(LOGFILE *self, const char *fname)
|
||||||
|
|
||||||
ez_db_create(&dbh, NULL, 0);
|
ez_db_create(&dbh, NULL, 0);
|
||||||
assert(dbh);
|
assert(dbh);
|
||||||
ez_db_open(dbh, NULL, dbFname, NULL, DB_BTREE, DB_CREATE, 0664);
|
ez_db_open(dbh, NULL, dbFname, NULL, DB_BTREE, DB_CREATE, G.cache.file_mode);
|
||||||
|
ez_chown(dbFname, getuid(), G.gid);
|
||||||
|
|
||||||
/* This will write all entries in the map do the database */
|
/* This will write all entries in the map do the database */
|
||||||
MAP_visitAllEntries(&self->addr.obsvTpl_map, (int(*)(void*,void*))ObsvTpl_db_put, dbh);
|
MAP_visitAllEntries(&self->addr.obsvTpl_map, (int(*)(void*,void*))ObsvTpl_db_put, dbh);
|
||||||
|
|
60
logType.c
60
logType.c
|
@ -118,9 +118,9 @@ LOGTYPE_proto_constructor(LOGTYPE *self, const struct logProtoType *proto)
|
||||||
{ /* Compute md5sum of all patterns put together */
|
{ /* Compute md5sum of all patterns put together */
|
||||||
MD5_CTX md5ctx;
|
MD5_CTX md5ctx;
|
||||||
MD5_Init(&md5ctx);
|
MD5_Init(&md5ctx);
|
||||||
const struct target *t;
|
const Target *t;
|
||||||
for(t= proto->targetArr; t->pattern; ++t) {
|
for(t= proto->targetArr; t->rxArr; ++t) {
|
||||||
MD5_Update(&md5ctx, t->pattern, strlen(t->pattern));
|
Target_MD5_update(t, &md5ctx);
|
||||||
}
|
}
|
||||||
static unsigned char sum[16];
|
static unsigned char sum[16];
|
||||||
MD5_Final(sum, &md5ctx);
|
MD5_Final(sum, &md5ctx);
|
||||||
|
@ -131,7 +131,7 @@ LOGTYPE_proto_constructor(LOGTYPE *self, const struct logProtoType *proto)
|
||||||
/* At this point we can call LOGTYPE_cacheName() */
|
/* At this point we can call LOGTYPE_cacheName() */
|
||||||
|
|
||||||
/* Keep the name of this logType's cache directory */
|
/* Keep the name of this logType's cache directory */
|
||||||
rc= snprintf(CacheDname, sizeof(CacheDname), "%s/%s", G.cacheDir, LOGTYPE_cacheName(self));
|
rc= snprintf(CacheDname, sizeof(CacheDname), "%s/%s", G.cache.dir, LOGTYPE_cacheName(self));
|
||||||
|
|
||||||
{ /*** Compute md5sum for each log file, then scan of read from cache ***/
|
{ /*** Compute md5sum for each log file, then scan of read from cache ***/
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ LOGTYPE_proto_constructor(LOGTYPE *self, const struct logProtoType *proto)
|
||||||
LOGFILE *f;
|
LOGFILE *f;
|
||||||
|
|
||||||
/* Use the cache, if available */
|
/* Use the cache, if available */
|
||||||
if(!access(CacheFname, F_OK))
|
if(!ez_access(CacheFname, F_OK))
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Construct object from cache file */
|
/* Construct object from cache file */
|
||||||
|
@ -215,8 +215,9 @@ LOGTYPE_proto_constructor(LOGTYPE *self, const struct logProtoType *proto)
|
||||||
|
|
||||||
} else { /* Scan the log file, write to new cache */
|
} else { /* Scan the log file, write to new cache */
|
||||||
|
|
||||||
if(access(CacheDname, F_OK)) {
|
if(ez_access(CacheDname, F_OK)) {
|
||||||
ez_mkdir(CacheDname, 0770);
|
ez_mkdir(CacheDname, G.cache.dir_mode);
|
||||||
|
ez_chown(CacheDname, getuid(), G.gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct object from log file */
|
/* Construct object from log file */
|
||||||
|
@ -328,26 +329,43 @@ LOGTYPE_init(CFGMAP *h_map, char *pfix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ /*--- Get all regex entries ---*/
|
{ /*--- Get the TIMESTAMP entry ---*/
|
||||||
snprintf(symBuf, len, "%s\\REGEX", pfix);
|
snprintf(symBuf, len, "%s\\TIMESTAMP", pfix);
|
||||||
|
const char *val= CFGMAP_find_last_value(h_map, symBuf);
|
||||||
|
|
||||||
|
if(val) {
|
||||||
|
|
||||||
|
snprintf(symBuf, len, "%s\\%s", pfix, val);
|
||||||
|
|
||||||
|
if(TS_init(&proto.ts, h_map, symBuf)) {
|
||||||
|
eprintf("ERROR: TS_init() failed.");
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{ /*--- Get all TARGET entries ---*/
|
||||||
|
|
||||||
|
snprintf(symBuf, len, "%s\\TARGET", pfix);
|
||||||
|
|
||||||
unsigned nFound= CFGMAP_find_tuples(h_map, rtn_arr, symBuf);
|
unsigned nFound= CFGMAP_find_tuples(h_map, rtn_arr, symBuf);
|
||||||
|
|
||||||
/* Get enough object to include a terminating entry */
|
/* Get enough object to include a terminating entry */
|
||||||
struct target targetArr[nFound+1];
|
Target targetArr[nFound+1];
|
||||||
/* Clear all bits in array */
|
/* Clear all bits in array */
|
||||||
memset(targetArr, 0, sizeof(struct target)*(nFound+1));
|
memset(targetArr, 0, sizeof(Target)*(nFound+1));
|
||||||
|
|
||||||
proto.targetArr= targetArr;
|
proto.targetArr= targetArr;
|
||||||
|
|
||||||
for(unsigned i= 0; i < nFound; ++i) {
|
for(unsigned i= 0; i < nFound; ++i) {
|
||||||
const struct CFGMAP_tuple *tpl= rtn_arr + i;
|
const struct CFGMAP_tuple *tpl= rtn_arr + i;
|
||||||
struct target *tg= targetArr + i;
|
Target *tg= targetArr + i;
|
||||||
tg->pattern= tpl->value;
|
snprintf(symBuf, len, "%s\\%s", pfix, tpl->value);
|
||||||
if(regex_compile(&tg->re, tg->pattern, REG_EXTENDED)) {
|
if(Target_init(tg, h_map, symBuf)) {
|
||||||
eprintf("ERROR: regex_compile(\"%s\") failed.", tg->pattern);
|
eprintf("ERROR: Target_init() failed.");
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the LOGTYPE object, place in global map */
|
/* Create the LOGTYPE object, place in global map */
|
||||||
|
@ -362,13 +380,17 @@ LOGTYPE_init(CFGMAP *h_map, char *pfix)
|
||||||
/* Place int the global map */
|
/* Place int the global map */
|
||||||
MAP_addStrKey(&G.logType_map, LOGTYPE_cacheName(obj), obj);
|
MAP_addStrKey(&G.logType_map, LOGTYPE_cacheName(obj), obj);
|
||||||
|
|
||||||
/* Free regex pattern data */
|
/* Free regex stuff */
|
||||||
for(unsigned i= 0; i < nFound; ++i) {
|
for(unsigned i= 0; i < nFound; ++i) {
|
||||||
struct target *tg= targetArr + i;
|
Target *tg= targetArr + i;
|
||||||
regfree(&tg->re);
|
Target_destructor(tg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(TS_is_prepared(&proto.ts)) {
|
||||||
|
TS_destructor(&proto.ts);
|
||||||
|
}
|
||||||
|
|
||||||
rtn= 0;
|
rtn= 0;
|
||||||
abort:
|
abort:
|
||||||
return rtn;
|
return rtn;
|
||||||
|
|
13
logType.h
13
logType.h
|
@ -24,14 +24,8 @@
|
||||||
#include "ban2fail.h"
|
#include "ban2fail.h"
|
||||||
#include "cfgmap.h"
|
#include "cfgmap.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
#include "target.h"
|
||||||
/*==================================================================*/
|
#include "timestamp.h"
|
||||||
/*===================== target =====================================*/
|
|
||||||
/*==================================================================*/
|
|
||||||
struct target {
|
|
||||||
const char *pattern;
|
|
||||||
regex_t re;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*==================================================================*/
|
/*==================================================================*/
|
||||||
/*===================== log file prototype =========================*/
|
/*===================== log file prototype =========================*/
|
||||||
|
@ -39,7 +33,8 @@ struct target {
|
||||||
struct logProtoType {
|
struct logProtoType {
|
||||||
const char *dir,
|
const char *dir,
|
||||||
*pfix;
|
*pfix;
|
||||||
struct target *targetArr;
|
TS ts; /* For log entry timestamps */
|
||||||
|
Target *targetArr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*==================================================================*/
|
/*==================================================================*/
|
||||||
|
|
94
offEntry.c
94
offEntry.c
|
@ -74,16 +74,29 @@ OFFENTRY_cache_constructor(OFFENTRY *self, const char *cacheFileEntry)
|
||||||
|
|
||||||
common_constructor(self);
|
common_constructor(self);
|
||||||
|
|
||||||
int rc= sscanf(cacheFileEntry, "%u %45s %2s"
|
long long ll;
|
||||||
,&self->count
|
|
||||||
,self->addr
|
|
||||||
,self->cntry);
|
|
||||||
|
|
||||||
if(2 > rc) {
|
int rc= sscanf(cacheFileEntry, "%u %u %lld %45s %2s"
|
||||||
|
, &self->count
|
||||||
|
, &self->severity
|
||||||
|
, &ll
|
||||||
|
, self->addr
|
||||||
|
, self->cntry
|
||||||
|
);
|
||||||
|
|
||||||
|
if(4 > rc) {
|
||||||
eprintf("ERROR: failed to interpret \"%s\"", cacheFileEntry);
|
eprintf("ERROR: failed to interpret \"%s\"", cacheFileEntry);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->latest= ll;
|
||||||
|
|
||||||
|
#ifdef qqDEBUG
|
||||||
|
if(self->severity) {
|
||||||
|
eprintf("%s : %u", self->addr, self->severity);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
rtn= self;
|
rtn= self;
|
||||||
abort:
|
abort:
|
||||||
return rtn;
|
return rtn;
|
||||||
|
@ -102,13 +115,28 @@ OFFENTRY_destructor(OFFENTRY *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OFFENTRY_register(OFFENTRY *self)
|
OFFENTRY_register(OFFENTRY *self, unsigned severity, time_t when)
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* Register the current failure try.
|
* Register the current failure try.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Keep track of count */
|
/* Keep track of count */
|
||||||
++self->count;
|
++self->count;
|
||||||
|
|
||||||
|
#ifdef qqDEBUG
|
||||||
|
if(severity) {
|
||||||
|
eprintf("Severity= %u", severity);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Keep track of most severe match */
|
||||||
|
if(self->severity < severity)
|
||||||
|
self->severity= severity;
|
||||||
|
|
||||||
|
/* Keep track of the most recent offense time */
|
||||||
|
if(self->latest < when)
|
||||||
|
self->latest= when;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,8 +146,10 @@ OFFENTRY_cacheWrite(OFFENTRY *self, FILE *fh)
|
||||||
* Write to the cache file in a form we can read later.
|
* Write to the cache file in a form we can read later.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ez_fprintf(fh, "%u %s %s\n"
|
ez_fprintf(fh, "%u %u %lld %s %s\n"
|
||||||
, self->count
|
, self->count
|
||||||
|
, self->severity
|
||||||
|
, (long long)self->latest
|
||||||
, self->addr
|
, self->addr
|
||||||
, self->cntry
|
, self->cntry
|
||||||
);
|
);
|
||||||
|
@ -133,11 +163,12 @@ OFFENTRY_print(OFFENTRY *self, FILE *fh)
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ez_fprintf(fh,
|
ez_fprintf(fh,
|
||||||
"\tLOGENTRY %p { addr= \"%s\", cntry= \"%2s\" count= %u }\n"
|
"\tLOGENTRY %p { addr= \"%s\", cntry= \"%2s\" count= %u, severity= %u }\n"
|
||||||
, self
|
, self
|
||||||
, self->addr
|
, self->addr
|
||||||
, self->cntry
|
, self->cntry
|
||||||
, self->count
|
, self->count
|
||||||
|
, self->severity
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -158,6 +189,12 @@ OFFENTRY_map_addr(OFFENTRY *self, MAP *h_rtnMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
e->count += self->count;
|
e->count += self->count;
|
||||||
|
|
||||||
|
if(e->severity < self->severity)
|
||||||
|
e->severity= self->severity;
|
||||||
|
|
||||||
|
if(e->latest < self->latest)
|
||||||
|
e->latest= self->latest;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,3 +208,44 @@ OFFENTRY_offenseCount(OFFENTRY *self, unsigned *h_sum)
|
||||||
//eprintf("%s numItems= %u", self->addr, PTRVEC_numItems(&self->rptObj_vec));
|
//eprintf("%s numItems= %u", self->addr, PTRVEC_numItems(&self->rptObj_vec));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
OFFENTRY_list(OFFENTRY *self, FILE *fh, int flags, unsigned nAllowed)
|
||||||
|
/********************************************************
|
||||||
|
* Print in listing form
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
static const struct bitTuple BlockBitTuples[]= {
|
||||||
|
{.name= "BLK", .bit= BLOCKED_FLG},
|
||||||
|
{.name= "+blk+", .bit= WOULD_BLOCK_FLG},
|
||||||
|
{.name= "-blk-", .bit= UNJUST_BLOCK_FLG},
|
||||||
|
{.name= "WL", .bit= WHITELIST_FLG},
|
||||||
|
{/* Terminating member */}
|
||||||
|
};
|
||||||
|
|
||||||
|
const static struct bitTuple dns_flagsArr[]= {
|
||||||
|
{.name= "~", .bit= PDNS_FWD_FAIL_FLG},
|
||||||
|
{.name= "!!", .bit= PDNS_FWD_NONE_FLG},
|
||||||
|
{.name= "NXDOMAIN", .bit= PDNS_NXDOMAIN_FLG},
|
||||||
|
{.name= "SERVFAIL", .bit= PDNS_SERVFAIL_FLG},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const static char *dns_fmt= "%u %-13s %-15s\t%5u/%-4d offenses %s [%s] %s %s\n",
|
||||||
|
*fmt= "%u %-13s %-15s\t%5u/%-4d offenses %s [%s]\n";
|
||||||
|
|
||||||
|
ez_fprintf(fh, self->dns.flags ? dns_fmt : fmt
|
||||||
|
, self->severity
|
||||||
|
, self->latest ? local_strftime(&self->latest, "%b %d %H:%M") : ""
|
||||||
|
, self->addr
|
||||||
|
, self->count
|
||||||
|
, nAllowed
|
||||||
|
, self->cntry[0] ? self->cntry : "--"
|
||||||
|
, bits2str(flags, BlockBitTuples)
|
||||||
|
, self->dns.name ? self->dns.name : ""
|
||||||
|
, bits2str(self->dns.flags, dns_flagsArr)
|
||||||
|
);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
24
offEntry.h
24
offEntry.h
|
@ -29,10 +29,14 @@
|
||||||
|
|
||||||
/* One of these for each offense found in a log file */
|
/* One of these for each offense found in a log file */
|
||||||
typedef struct _OFFENTRY {
|
typedef struct _OFFENTRY {
|
||||||
unsigned logfile_ndx;
|
|
||||||
|
unsigned count,
|
||||||
|
severity;
|
||||||
|
|
||||||
|
time_t latest;
|
||||||
|
|
||||||
char addr[46],
|
char addr[46],
|
||||||
cntry[3];
|
cntry[3];
|
||||||
unsigned count;
|
|
||||||
|
|
||||||
/* This data populated by PDNS_lookup() */
|
/* This data populated by PDNS_lookup() */
|
||||||
struct {
|
struct {
|
||||||
|
@ -78,19 +82,11 @@ OFFENTRY_destructor(OFFENTRY *self);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
OFFENTRY_register(OFFENTRY *self);
|
OFFENTRY_register(OFFENTRY *self, unsigned severity, time_t when);
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* Register the current failure try.
|
* Register the current failure try.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0
|
|
||||||
int
|
|
||||||
OFFENTRY_is_blocked_country(const OFFENTRY *self);
|
|
||||||
/********************************************************
|
|
||||||
* Return 1 if the country is blocked, or 0.
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
int
|
||||||
OFFENTRY_cacheWrite(OFFENTRY *self, FILE *fh);
|
OFFENTRY_cacheWrite(OFFENTRY *self, FILE *fh);
|
||||||
/********************************************************
|
/********************************************************
|
||||||
|
@ -103,6 +99,12 @@ OFFENTRY_print(OFFENTRY *self, FILE *fh);
|
||||||
* Print a human readable representation of *self.
|
* Print a human readable representation of *self.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
OFFENTRY_list(OFFENTRY *self, FILE *fh, int flags, unsigned nAllowed);
|
||||||
|
/********************************************************
|
||||||
|
* Print in listing form
|
||||||
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
OFFENTRY_map_addr(OFFENTRY *self, MAP *h_rtnMap);
|
OFFENTRY_map_addr(OFFENTRY *self, MAP *h_rtnMap);
|
||||||
/********************************************************
|
/********************************************************
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2019 by John D. Robertson *
|
||||||
|
* john@rrci.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <assert.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "target.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
Target_init(Target *self, CFGMAP *h_map, const char *pfix)
|
||||||
|
/********************************************************
|
||||||
|
* Prepare for use from config map
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int rtn= -1;
|
||||||
|
memset(self, 0, sizeof(*self));
|
||||||
|
|
||||||
|
self->flags |= TARGET_INIT_FLG;
|
||||||
|
|
||||||
|
unsigned arr_sz= CFGMAP_numTuples(h_map);
|
||||||
|
struct CFGMAP_tuple rtn_arr[arr_sz];
|
||||||
|
|
||||||
|
size_t len= strlen(pfix)+1024;
|
||||||
|
char symBuf[len];
|
||||||
|
|
||||||
|
{ /*--- Check for "SEVERITY" symbol ---*/
|
||||||
|
snprintf(symBuf, len, "%s\\SEVERITY", pfix);
|
||||||
|
|
||||||
|
if(CFGMAP_query_last_uint(h_map, &self->severity, 0, symBuf)) {
|
||||||
|
eprintf("ERROR: cannot interpret \"SEVERITY\" entry for REGEX %s", pfix);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
#ifdef qqDEBUG
|
||||||
|
eprintf("%s = %u", symBuf, self->severity);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /*--- Get all REGEX entries ---*/
|
||||||
|
snprintf(symBuf, len, "%s\\REGEX", pfix);
|
||||||
|
self->nRx= CFGMAP_find_tuples(h_map, rtn_arr, symBuf);
|
||||||
|
|
||||||
|
self->rxArr= calloc(self->nRx, sizeof(struct TargetRx));
|
||||||
|
assert(self->rxArr);
|
||||||
|
|
||||||
|
for(unsigned i= 0; i < self->nRx; ++i) {
|
||||||
|
|
||||||
|
const struct CFGMAP_tuple *tpl= rtn_arr + i;
|
||||||
|
struct TargetRx *rx= self->rxArr + i;
|
||||||
|
|
||||||
|
/* Compile regular expression */
|
||||||
|
rx->pattern= tpl->value;
|
||||||
|
if(regex_compile(&rx->re, rx->pattern, REG_EXTENDED)) {
|
||||||
|
eprintf("ERROR: regex_compile(\"%s\") failed.", rx->pattern);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtn= 0;
|
||||||
|
abort:
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
Target_destructor(Target *self)
|
||||||
|
/********************************************************
|
||||||
|
* Free resources.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
if(self->nRx && self->rxArr) {
|
||||||
|
for(unsigned i= 0; i < self->nRx; ++i) {
|
||||||
|
struct TargetRx *rx= self->rxArr + i;
|
||||||
|
regfree(&rx->re);
|
||||||
|
}
|
||||||
|
free(self->rxArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Target_scan(const Target *self, char *rsltBuf, unsigned buf_sz, const char *str)
|
||||||
|
/********************************************************
|
||||||
|
* Scan a string to obtain the address.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int rtn= EOF;
|
||||||
|
|
||||||
|
/* Exit on first match */
|
||||||
|
for(unsigned i= 0; i < self->nRx; ++i) {
|
||||||
|
|
||||||
|
const struct TargetRx *rx= self->rxArr+i;
|
||||||
|
|
||||||
|
regmatch_t matchArr[2];
|
||||||
|
if(0 != regexec(&rx->re, str, 2, matchArr, 0) || -1 == matchArr[1].rm_so)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unsigned len= matchArr[1].rm_eo - matchArr[1].rm_so;
|
||||||
|
|
||||||
|
strncpy(rsltBuf, str+matchArr[1].rm_so, buf_sz-1);
|
||||||
|
rsltBuf[MIN(len, buf_sz-1)]= '\0';
|
||||||
|
rtn= 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
abort:
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Target_MD5_update(const Target *self, MD5_CTX *ctx)
|
||||||
|
/********************************************************
|
||||||
|
* For computing MD5 checksum of cumulative patterns.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
for(unsigned i= 0; i < self->nRx; ++i) {
|
||||||
|
const struct TargetRx *rx= self->rxArr+i;
|
||||||
|
MD5_Update(ctx, rx->pattern, strlen(rx->pattern));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2019 by John D. Robertson *
|
||||||
|
* john@rrci.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef TARGET_H
|
||||||
|
#define TARGET_H
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <openssl/md5.h>
|
||||||
|
#include "cfgmap.h"
|
||||||
|
|
||||||
|
struct TargetRx {
|
||||||
|
const char *pattern;
|
||||||
|
regex_t re;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _Target {
|
||||||
|
enum {
|
||||||
|
TARGET_INIT_FLG=1<<0
|
||||||
|
} flags;
|
||||||
|
unsigned severity,
|
||||||
|
nRx;
|
||||||
|
struct TargetRx *rxArr;
|
||||||
|
} Target;
|
||||||
|
|
||||||
|
#define Target_severity(s) \
|
||||||
|
((const unsigned)(s)->severity)
|
||||||
|
|
||||||
|
#define Target_is_init(s) \
|
||||||
|
((const int)(s)->flags)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
Target_init(Target *self, CFGMAP *h_map, const char *pfix);
|
||||||
|
/********************************************************
|
||||||
|
* Prepare for use from config map
|
||||||
|
*/
|
||||||
|
|
||||||
|
void*
|
||||||
|
Target_destructor(Target *self);
|
||||||
|
/********************************************************
|
||||||
|
* Free resources.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
Target_scan(const Target *self, char *rsltBuf, unsigned buf_sz, const char *str);
|
||||||
|
/********************************************************
|
||||||
|
* Scan a string to obtain the address.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
Target_MD5_update(const Target *self, MD5_CTX *ctx);
|
||||||
|
/********************************************************
|
||||||
|
* For computing MD5 checksum of cumulative patterns.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2019 by John D. Robertson *
|
||||||
|
* john@rrci.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include "ez_libc.h"
|
||||||
|
#include "timestamp.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum Flags {
|
||||||
|
GUESS_YR_FLG= 1<<0
|
||||||
|
};
|
||||||
|
|
||||||
|
const static struct bitTuple FlagsBitTupleArr[]= {
|
||||||
|
{.name= "GUESS_YEAR", .bit= GUESS_YR_FLG},
|
||||||
|
{/* Terminating member */}
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
TS_init(TS *self, CFGMAP *h_map, const char *pfix)
|
||||||
|
/********************************************************
|
||||||
|
* Initialize timestamp from config map.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int rtn= -1;
|
||||||
|
memset(self, 0, sizeof(*self));
|
||||||
|
|
||||||
|
size_t len= strlen(pfix)+1024;
|
||||||
|
char symBuf[len];
|
||||||
|
|
||||||
|
{ /*--- Check for "REGEX" symbol ---*/
|
||||||
|
snprintf(symBuf, len, "%s\\REGEX", pfix);
|
||||||
|
/* CFGMAP is left in place, so we don't need to strdup() */
|
||||||
|
self->pattern= CFGMAP_find_last_value(h_map, symBuf);
|
||||||
|
|
||||||
|
if(!self->pattern) {
|
||||||
|
eprintf("ERROR: cannot find \"REGEX\" entry for ENTRY_TIMESTAMP %s", pfix);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(regex_compile(&self->re, self->pattern, REG_EXTENDED)) {
|
||||||
|
eprintf("ERROR: regex_compile(\"%s\") failed.", self->pattern);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /*--- Check for "STRPTIME" symbol ---*/
|
||||||
|
snprintf(symBuf, len, "%s\\STRPTIME", pfix);
|
||||||
|
/* CFGMAP is left in place, so we don't need to strdup() */
|
||||||
|
self->strptime_fmt= CFGMAP_find_last_value(h_map, symBuf);
|
||||||
|
|
||||||
|
if(!self->strptime_fmt) {
|
||||||
|
eprintf("ERROR: cannot find \"STRPTIME\" entry for ENTRY_TIMESTAMP %s", pfix);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ /*--- Check for "FLAGS" symbol ---*/
|
||||||
|
const char *flagStr;
|
||||||
|
snprintf(symBuf, len, "%s\\FLAGS", pfix);
|
||||||
|
|
||||||
|
flagStr= CFGMAP_find_last_value(h_map, symBuf);
|
||||||
|
/* This is optional */
|
||||||
|
if(flagStr) {
|
||||||
|
int rc= str2bits(&self->flags, flagStr, FlagsBitTupleArr);
|
||||||
|
if(rc) {
|
||||||
|
eprintf("ERROR: cannot interpret \"FLAGS\" entry for ENTRY_TIMESTAMP %s", pfix);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtn= 0;
|
||||||
|
abort:
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
TS_destructor(TS *self)
|
||||||
|
/********************************************************
|
||||||
|
* Free resources.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
if(self->pattern)
|
||||||
|
regfree(&self->re);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
TS_scan(const TS *self, time_t *rslt, const char *str, const struct tm *pTmRef)
|
||||||
|
/********************************************************
|
||||||
|
* Scan a string to obtain the timestamp.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int rtn= -1;
|
||||||
|
|
||||||
|
/* If there is no match, continue looking */
|
||||||
|
regmatch_t matchArr[2];
|
||||||
|
if(0 != regexec(&self->re, str, 2, matchArr, 0) || -1 == matchArr[1].rm_so) {
|
||||||
|
eprintf("ERROR: failed to identify date in \"%s\"", str);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned len= matchArr[1].rm_eo - matchArr[1].rm_so;
|
||||||
|
static char date[128];
|
||||||
|
strncpy(date, str+matchArr[1].rm_so, sizeof(date)-1);
|
||||||
|
date[MIN(len, sizeof(date)-1)]= '\0';
|
||||||
|
static struct tm tm;
|
||||||
|
memset(&tm, 0, sizeof(tm));
|
||||||
|
tm.tm_isdst= -1;
|
||||||
|
|
||||||
|
const char *lc= ez_strptime(date, self->strptime_fmt, &tm);
|
||||||
|
|
||||||
|
/* We may have to guess the year */
|
||||||
|
if(self->flags & GUESS_YR_FLG) {
|
||||||
|
|
||||||
|
tm.tm_year= pTmRef->tm_year;
|
||||||
|
|
||||||
|
if(tm.tm_mon > pTmRef->tm_mon)
|
||||||
|
--tm.tm_year;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rslt= mktime(&tm);
|
||||||
|
//eprintf("Date string= \"%s\", lc= \"%s\", =? \"%s\"", date, lc, ctime(rslt));
|
||||||
|
|
||||||
|
rtn= 0;
|
||||||
|
abort:
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2019 by John D. Robertson *
|
||||||
|
* john@rrci.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the *
|
||||||
|
* Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef TIMESTAMP_H
|
||||||
|
#define TIMESTAMP_H
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <regex.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "cfgmap.h"
|
||||||
|
|
||||||
|
typedef struct _TS {
|
||||||
|
const char *pattern;
|
||||||
|
regex_t re;
|
||||||
|
const char *strptime_fmt;
|
||||||
|
int64_t flags;
|
||||||
|
} TS;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TS_is_prepared(s) \
|
||||||
|
((s)->pattern ? 1 : 0)
|
||||||
|
|
||||||
|
int
|
||||||
|
TS_init(TS *self, CFGMAP *h_map, const char *pfix);
|
||||||
|
/********************************************************
|
||||||
|
* Initialize timestamp from config map.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void*
|
||||||
|
TS_destructor(TS *self);
|
||||||
|
/********************************************************
|
||||||
|
* Free resources.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
TS_scan(const TS *self, time_t *rslt, const char *str, const struct tm *pTmRef);
|
||||||
|
/********************************************************
|
||||||
|
* Scan a string to obtain the timestamp.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue