Implemented cached reporting

This commit is contained in:
john 2019-12-02 21:56:55 -05:00
parent ff77f50dba
commit b6d4d8df3f
19 changed files with 1094 additions and 96 deletions

View File

@ -15,9 +15,11 @@ src := \
ban2fail.c \
cfgmap.c \
cntry.c \
dynstack.c \
es.c \
ez_es.c \
ez_libc.c \
ez_libdb.c \
ez_libz.c \
iptables.c \
logType.c \
@ -25,13 +27,14 @@ src := \
map.c \
maxoff.c \
msgqueue.c \
obsvTpl.c \
offEntry.c \
pdns.c \
ptrvec.c \
str.c \
util.c \
libs := z crypto GeoIP pthread
libs := z crypto GeoIP pthread db
endif
ifeq ($(exe), fsckdns)

View File

@ -79,7 +79,7 @@ AddrRPT_addr_constructor(AddrRPT *self, const char *addr)
memset(self, 0, sizeof(*self));
strncpy(self->addr, addr, sizeof(self->addr)-1);
PTRVEC_constructor(&self->vec, 100);
PTRVEC_constructor(&self->match_vec, 100);
/* Stamp with serial number so reporting at the end can be
* in the order addresses were supplied on the command
@ -98,10 +98,10 @@ AddrRPT_destructor(AddrRPT *self)
*/
{
Match *m;
while((m= PTRVEC_remHead(&self->vec)))
while((m= PTRVEC_remHead(&self->match_vec)))
Match_destroy(m);
PTRVEC_destroy(&self->vec);
PTRVEC_destroy(&self->match_vec);
return self;
}
@ -114,7 +114,7 @@ AddrRPT_addLine(AddrRPT *self, LOGFILE *lf, const char *line)
Match *m;
Match_create(m, lf, line);
assert(m);
PTRVEC_addTail(&self->vec, m);
PTRVEC_addTail(&self->match_vec, m);
return 0;
}
@ -127,12 +127,12 @@ AddrRPT_print(AddrRPT *self, FILE *fh)
Match *m;
unsigned i;
LOGFILE *lf= NULL;
ez_fprintf(fh, "============== Report for %s\r\n", self->addr);
ez_fprintf(fh, "====== Report for %s ======\r\n", self->addr);
PTRVEC_loopFwd(&self->vec, i, m) {
PTRVEC_loopFwd(&self->match_vec, i, m) {
if(lf != m->lf) {
ez_fprintf(fh, "%s\r\n", LOGFILE_logFilePath(m->lf));
ez_fprintf(fh, "------- %s -------------\r\n", LOGFILE_logFname(m->lf));
lf= m->lf;
}
ez_fprintf(fh, "%s\r\n", m->line);

View File

@ -32,8 +32,8 @@ typedef struct _AddrRPT {
char addr[46];
/* Store match records here */
PTRVEC vec;
/* Store vector of match objects */
PTRVEC match_vec;
} AddrRPT;

View File

@ -89,7 +89,7 @@ struct Global G= {
.version= {
.major= 0,
.minor= 13,
.patch= 0
.patch= 1
},
.bitTuples.flags= GlobalFlagBitTuples
@ -279,9 +279,6 @@ main(int argc, char **argv)
/* Place it in global map */
MAP_addStrKey(&G.rpt.AddrRPT_map, addr, ar);
/* Don't touch the cache */
G.flags |= GLB_NO_CACHE_FLG;
}
@ -307,7 +304,7 @@ main(int argc, char **argv)
/* Obtain a file lock to protect cache files */
/*===========================================================*/
if(!(G.flags & GLB_NO_CACHE_FLG)) {
{
/* Make sure the file exists by open()'ing */
lock_fd= open(G.lockPath, O_CREAT|O_WRONLY|O_CLOEXEC, 0640);
if(-1 == lock_fd) {
@ -631,13 +628,13 @@ main(int argc, char **argv)
fflush(G.rpt.fh);
rtn= EXIT_SUCCESS;
abort:
/* Wait for pager to finish, if it is running */
if(S.flags & PAGER_RUNNING_FLG)
ez_pclose(G.rpt.fh);
rtn= EXIT_SUCCESS;
abort:
/* Make sure lock file is unlocked */
if(-1 != lock_fd) {
flock(lock_fd, LOCK_UN);

View File

@ -40,6 +40,8 @@
#define N_ADDRESSES_HINT 10000
#define BUCKET_DEPTH_HINT 10
#define MD5SUM_SZ 32
/* How long to wait for reverse DNS lookups before giving up and
* moving on with the report.
*/
@ -67,7 +69,6 @@ enum GlobalFlg_enum {
GLB_PRINT_LOGFILE_NAMES_FLG=1<<5,
GLB_DNS_LOOKUP_FLG =1<<6,
GLB_DNS_FILTER_BAD_FLG =1<<7,
GLB_NO_CACHE_FLG =1<<8,
GLB_LONG_LISTING_MASK = GLB_LIST_CNTRY_FLG|GLB_LIST_ADDR_FLG
};

179
dynstack.c Normal file
View File

@ -0,0 +1,179 @@
/***************************************************************************
* 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 <stdlib.h>
#include <string.h>
#include "dynstack.h"
#define elAddress(s, ndx)\
((s)->stk_ptr + (ndx) * (s)->elsize)
DS*
DS_constructor(DS *self, unsigned int elmtSize, unsigned int numElmts )
/******************************************************************
* Open a dynamic stack, and get a key with which to interact with the stack.
*/
{
if(!self) return NULL;
memset(self, 0, sizeof(*self));
if(!( self->stk_ptr = malloc( elmtSize*numElmts ) )) return NULL;
self->elsize = elmtSize;
self->size = numElmts;
return self;
}
int
DS_sinit(DS *self, unsigned int elmtSize, unsigned int numElmts)
/****************************************************************
* Initializion for static instance of DS. Initializes once per
* process, and reset() all other times.
*/
{
int rtn= 1;
if(!self->stk_ptr) {
if(!DS_constructor(self, elmtSize, numElmts)) goto abort;
} else {
DS_reset(self);
}
rtn= 0;
abort:
return rtn;
}
void*
DS_destructor(DS *self )
/******************************************************************
* Close the dynamic stack and free all memory.
*/
{
if(self->stk_ptr) free( self->stk_ptr );
return self;
}
static void*
top( DS *self )
/********************* top() ***********************************
* return a pointer to the top of the stack.
*/
{
if(!self->count) return NULL;
return (void *)elAddress( self, self->count - 1);
}
#define copy(s, dst, src)\
memcpy(dst, src, (s)->elsize)
int
DS_top( DS *self, void *dest_ptr )
/******************** DS_top() ************************************
* Pop the item off the top of the stack.
*/
{
void *src_ptr;
if(!self->count) return -1;
src_ptr= (void*)elAddress(self, self->count - 1);
/* Get a copy of the stack item */
copy(self, dest_ptr, src_ptr);
return 0;
}
int
DS_pop( DS *self, void *dest_ptr )
/******************** DS_pop() ************************************
* Pop the item off the top of the stack.
*/
{
/* Try to get a copy of the top stack item */
if(DS_top(self, dest_ptr)) return -1;
/* decrement the stack pointer */
--self->count;
return 0;
}
int
DS_push( DS *self, const void *src_ptr )
/******************** DS_push() ***********************************
* Push an item on to the dynamic stack.
*/
{
char *dest_ptr;
/* If more memory is needed, get it */
if(self->count == self->size) {
unsigned new_sz= self->size*2;
char *ptr;
if(!(ptr = realloc( self->stk_ptr, self->elsize * new_sz ))) return -1;
self->stk_ptr= ptr;
self->size= new_sz;
}
/* Increment the stack pointer */
++self->count;
/* Get the address to the destination memory */
dest_ptr = elAddress( self, self->count - 1);
/* Make a copy of this item */
copy(self, dest_ptr, src_ptr);
return 0;
}
int
DS_entry_exists(const DS *self, const void *target_ptr)
/******************************************************************
* Return true if the item exists in the stack
*/
{
unsigned i;
char *p;
for(i= 0; i < self->count; i++) {
p= self->stk_ptr + i * self->elsize;
if(!memcmp(p, target_ptr, self->elsize)) return 1;
}
return 0;
}
int
DS_visitAllEntries(DS *self, int (* func)(void *item_ptr, void *data), void *data)
/******************************************************************************/
{
for(unsigned i= 0; i < self->count; ++i) {
void *item_ptr= self->stk_ptr + i * self->elsize;
int rc= (*func)(item_ptr, data);
if(rc) return rc;
}
return 0;
}

107
dynstack.h Normal file
View File

@ -0,0 +1,107 @@
/***************************************************************************
* 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 DS_H
#define DS_H
typedef struct _DS {
unsigned size,
count,
elsize;
char *stk_ptr;
} DS;
#define DS_currBuf_sz(s) \
((const unsigned)(s)->size)
#define DS_numItems(s)\
((const unsigned)(s)->count)
/* Return the number of items currently on the stack */
#define DS_ptr(s)\
((void*)(s)->stk_ptr)
/* Return the stack pointer */
#define DS_qsort(s, cmp_func)\
qsort((s)->stk_ptr, (s)->count, (s)->elsize, cmp_func)
/* Sort the stack using qsort() */
#define DS_reset(s) \
((s)->count= 0)
/* Reset the stack so that no items are contained */
#ifdef __cplusplus
extern "C" {
#endif
#define DS_create(p, elmtSize, numElmts) \
((p)= (DS_constructor((p)=malloc(sizeof(DS)), elmtSize, numElmts) ? (p) : ( p ? realloc(DS_destructor(p),0) : 0 )))
DS*
DS_constructor(DS *self, unsigned int elmtSize, unsigned int numElmts);
/* Initialize the dynamic stack object. You must provide the
* size of the elements (in bytes) you wish to use the stack for, and
* the approximate max number of element you think you will use.
*/
int
DS_sinit(DS *self, unsigned int elmtSize, unsigned int numElmts);
/* Initializion for static instance of DS. Initializes once per
* process, and reset() all other times.
*/
#define DS_destroy(s) \
{if(DS_destructor(s)) {free(s);s=0;}}
void*
DS_destructor(DS *self);
/* Close the dynamic stack, free all memory, etc. */
int
DS_top(DS *self, void *dest_ptr);
/* Copy the element at the top of the stack to the dest_ptr buffer
* area.
*/
int
DS_pop(DS *self, void *dest_ptr);
/* Pop the top element off the stack and copy it to the dest_ptr
* buffer area
*/
int
DS_push(DS *self, const void *src_ptr);
/* Push a new element on the top of the stack. */
int
DS_entry_exists(const DS *self, const void *target_ptr);
/* Return true if the item exists in the stack */
int
DS_visitAllEntries(DS *self, int (* func)(void *item_ptr, void *data), void *data);
/******************************************************************************
* Visit all entries in the stack. if (*func) returns nonzero, then
* the process stops and DS_visitAllEntries will return non-zero.
*/
#ifdef __cplusplus
}
#endif
#endif /* DS_H */

157
ez_libdb.c Normal file
View File

@ -0,0 +1,157 @@
/***************************************************************************
* 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 <stdlib.h>
#include "util.h"
#include "ez_libdb.h"
/***************************************************/
int _ez_db_create(
const char *fileName,
int lineNo,
const char *funcName,
DB **dbp,
DB_ENV *dbenv,
u_int32_t flags
)
{
int rtn= db_create (dbp, dbenv, flags);
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_create() failed");
abort();
}
/***************************************************/
int _ez_db_open(
const char *fileName,
int lineNo,
const char *funcName,
DB *db,
DB_TXN *txnid,
const char *file,
const char *database,
DBTYPE type,
u_int32_t flags,
int mode
)
{
//eprintf("Opening file (%p) \"%s\"", db, file);
int rtn= db->open(db, txnid, file, database, type, flags, mode);
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->open(\"%s\") failed", database);
abort();
}
/***************************************************/
int _ez_db_put(
const char *fileName,
int lineNo,
const char *funcName,
DB *db,
DB_TXN *txnid,
DBT *key,
DBT *data,
u_int32_t flags
)
{
int rtn= db->put(db, txnid, key, data, flags);
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->put() failed");
abort();
}
/***************************************************/
int _ez_db_get(
const char *fileName,
int lineNo,
const char *funcName,
DB *db,
DB_TXN *txnid,
DBT *key,
DBT *data,
u_int32_t flags
)
{
int rtn= db->get(db, txnid, key, data, flags);
switch(rtn) {
case 0:
case DB_NOTFOUND:
return rtn;
}
/* _sys_eprintf() will pass errno to db_sterror */
errno= rtn;
_sys_eprintf((const char*(*)(int))db_strerror, fileName, lineNo, funcName, "DB->get() failed");
abort();
}
/***************************************************/
int _ez_db_del(
const char *fileName,
int lineNo,
const char *funcName,
DB *db,
DB_TXN *txnid,
DBT *key,
u_int32_t flags
)
{
int rtn= db->del(db, txnid, key, flags);
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->del() failed");
abort();
}
/***************************************************/
int _ez_db_close(
const char *fileName,
int lineNo,
const char *funcName,
DB *db,
u_int32_t flags
)
{
//eprintf("Closing database (%p)", db);
int rtn= db->close(db, flags);
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->close() failed");
abort();
}

109
ez_libdb.h Normal file
View File

@ -0,0 +1,109 @@
/***************************************************************************
* 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 EZ_LIBDB_H
#define EZ_LIBDB_H
/* Simplified interface to libanl functions */
#define _GNU_SOURCE
#include <db.h>
#ifdef __cplusplus
extern "C" {
#endif
#define ez_db_create(dbp, dbenv, flags) \
_ez_db_create(__FILE__, __LINE__, __FUNCTION__, dbp, dbenv, flags)
int _ez_db_create(
const char *fileName,
int lineNo,
const char *funcName,
DB **dbp,
DB_ENV *dbenv,
u_int32_t flags
);
#define ez_db_open(db, txnid, file, database, type, flags, mode ) \
_ez_db_open(__FILE__, __LINE__, __FUNCTION__, db, txnid, file, database, type, flags, mode)
int _ez_db_open(
const char *fileName,
int lineNo,
const char *funcName,
DB *db,
DB_TXN *txnid,
const char *file,
const char *database,
DBTYPE type,
u_int32_t flags,
int mode
);
#define ez_db_put(db, txnid, key, data, flags) \
_ez_db_put(__FILE__, __LINE__, __FUNCTION__, db, txnid, key, data, flags)
int _ez_db_put(
const char *fileName,
int lineNo,
const char *funcName,
DB *db,
DB_TXN *txnid,
DBT *key,
DBT *data,
u_int32_t flags
);
#define ez_db_get(db, txnid, key, data, flags) \
_ez_db_get(__FILE__, __LINE__, __FUNCTION__, db, txnid, key, data, flags)
int _ez_db_get(
const char *fileName,
int lineNo,
const char *funcName,
DB *db,
DB_TXN *txnid,
DBT *key,
DBT *data,
u_int32_t flags
);
#define ez_db_del(db, txnid, key, flags) \
_ez_db_del(__FILE__, __LINE__, __FUNCTION__, db, txnid, key, flags)
int _ez_db_del(
const char *fileName,
int lineNo,
const char *funcName,
DB *db,
DB_TXN *txnid,
DBT *key,
u_int32_t flags
);
#define ez_db_close(db, flags) \
_ez_db_close(__FILE__, __LINE__, __FUNCTION__, db, flags)
int _ez_db_close(
const char *fileName,
int lineNo,
const char *funcName,
DB *db,
u_int32_t flags
);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -16,6 +16,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#define _GNU_SOURCE
#include <stdlib.h>
#include "ez_libz.h"
@ -190,3 +191,24 @@ char* _ez_gzgets (
return rtn;
}
/***************************************************/
z_off_t _ez_gztell(
const char *fileName,
int lineNo,
const char *funcName,
gzFile file
)
{
z_off_t rtn= gztell(file);
if(-1 != rtn) return rtn;
int err;
const char *str= gzerror(file, &err);
if(Z_ERRNO == err) {
_sys_eprintf((const char*(*)(int))strerror, fileName, lineNo, funcName, "ERROR: gztell()");
} else {
_eprintf(fileName, lineNo, funcName, "ERROR: gztell() [ %s ]", str);
}
abort();
}

View File

@ -20,6 +20,7 @@
#define EZ_GZFILE_H
/* Simplified interface to libz file functions */
#define _GNU_SOURCE
#include <zlib.h>
#ifdef __cplusplus
@ -88,6 +89,15 @@ z_off_t _ez_gzseek(
int whence
);
#define ez_gztell(file) \
_ez_gztell(__FILE__, __LINE__, __FUNCTION__, file)
z_off_t _ez_gztell(
const char *fileName,
int lineNo,
const char *funcName,
gzFile file
);
#define ez_gzgets(file, buf, len) \
_ez_gzgets(__FILE__, __LINE__, __FUNCTION__, file, buf, len)
char* _ez_gzgets (

187
logFile.c
View File

@ -19,6 +19,7 @@
#define _GNU_SOURCE
#include <assert.h>
#include <ctype.h>
#include <db.h>
#include <errno.h>
#include <limits.h>
#include <openssl/md5.h>
@ -28,19 +29,21 @@
#include "addrRpt.h"
#include "cntry.h"
#include "offEntry.h"
#include "logFile.h"
#include "dynstack.h"
#include "ez_libc.h"
#include "ez_libdb.h"
#include "ez_libz.h"
#include "logFile.h"
#include "obsvTpl.h"
#include "offEntry.h"
#include "util.h"
enum {
NOFFENSES_CACHED_FLG =1<<0
};
/*==================================================================*/
/*=================== LOGFILE ======================================*/
/*==================================================================*/
enum {
NOFFENSES_CACHED_FLG =1<<0
};
static void
common_constructor(LOGFILE *self)
@ -49,38 +52,85 @@ common_constructor(LOGFILE *self)
*/
{
memset(self, 0, sizeof(*self));
MAP_constructor(&self->addr2offEntry_map, N_ADDRESSES_HINT/BUCKET_DEPTH_HINT, BUCKET_DEPTH_HINT);
MAP_constructor(&self->addr.offEntry_map, N_ADDRESSES_HINT/BUCKET_DEPTH_HINT, BUCKET_DEPTH_HINT);
MAP_constructor(&self->addr.obsvTpl_map, N_ADDRESSES_HINT/BUCKET_DEPTH_HINT, BUCKET_DEPTH_HINT);
}
LOGFILE*
LOGFILE_cache_constructor(LOGFILE *self, const char *fname)
LOGFILE_cache_constructor(
LOGFILE *self,
const char *cacheFname,
const char *logFname
)
/******************************************************************
* Initialize an instance of a LOGFILE class from a cache file.
*/
{
LOGFILE *rtn= NULL;
common_constructor(self);
FILE *fh= ez_fopen(fname, "r");
/* Not reentrant! */
gzFile log_fh= NULL;
self->logFname= strdup(logFname);
/* Open our database, if it exists */
DB *db= NULL;
static char dbFname[PATH_MAX];
snprintf(dbFname, sizeof(dbFname), "%s.db", cacheFname);
if(0 == access(dbFname, F_OK)) {
ez_db_create(&db, NULL, 0);
ez_db_open(db, NULL, dbFname, NULL, DB_BTREE, DB_RDONLY, 0664);
}
/* Open the cache file */
FILE *cache_fh= ez_fopen(cacheFname, "r");
static char buf[256];
while(ez_fgets(buf, sizeof(buf), fh)) {
while(ez_fgets(buf, sizeof(buf), cache_fh)) {
OFFENTRY *e;
OFFENTRY_cache_create(e, buf);
if(!e) goto abort;
MAP_addStrKey(&self->addr2offEntry_map, e->addr, e);
assert(e);
MAP_addStrKey(&self->addr.offEntry_map, e->addr, e);
AddrRPT *ar= MAP_findStrItem(&G.rpt.AddrRPT_map, e->addr);
if(ar && db) {
static ObsvTpl otpl;
/* Initialize or reset static instance */
ObsvTpl_sinit(&otpl, self, e->addr);
/* May not exist in database */
/* Fetch from database */
if(0 == ObsvTpl_db_get(&otpl, db)) {
if(!log_fh)
log_fh= ez_gzopen(logFname, "r");
/* Place observations in ar */
ObsvTpl_put_AddrRPT(&otpl, log_fh, ar);
}
}
}
rtn= self;
abort:
if(fh) ez_fclose(fh);
if(db) ez_db_close(db, 0);
if(log_fh) ez_gzclose(log_fh);
if(cache_fh) ez_fclose(cache_fh);
return rtn;
}
LOGFILE*
LOGFILE_log_constructor(LOGFILE *self, const struct logProtoType *h_protoType, const char *fname)
LOGFILE_log_constructor(
LOGFILE *self,
const struct logProtoType *h_protoType,
const char *logFname
)
/******************************************************************
* Initialize an instance of a LOGFILE from an actual log file.
*/
@ -89,17 +139,22 @@ LOGFILE_log_constructor(LOGFILE *self, const struct logProtoType *h_protoType, c
common_constructor(self);
self->logFname= strdup(logFname);
static char lbuf[1024];
/* Open the log file for reading */
gzFile fh= ez_gzopen(fname, "r");
gzFile gzfh= ez_gzopen(logFname, "r");
/* Loop through one line at a time */
while(ez_gzgets(fh, lbuf, sizeof(lbuf)-1)) {
size_t len= strlen(lbuf);
while(gzfh) {
z_off_t pos= ez_gztell(gzfh);
if(!ez_gzgets(gzfh, lbuf, sizeof(lbuf)-1)) break;
size_t line_len= strlen(lbuf);
/* Get rid of trailing newline, spaces */
while(len && isspace(lbuf[len-1]))
lbuf[--len]= '\0';
while(line_len && isspace(lbuf[line_len-1]))
lbuf[--line_len]= '\0';
/* Search for a match in the targets */
for(struct target *tg= h_protoType->targetArr; tg->pattern; ++tg) {
@ -115,26 +170,47 @@ LOGFILE_log_constructor(LOGFILE *self, const struct logProtoType *h_protoType, c
strncpy(addr, lbuf+matchArr[1].rm_so, sizeof(addr)-1);
addr[MIN(len, sizeof(addr)-1)]= '\0';
OFFENTRY *e= MAP_findStrItem(&self->addr2offEntry_map, addr);
OFFENTRY *e= MAP_findStrItem(&self->addr.offEntry_map, addr);
if(!e) {
OFFENTRY_addr_create(e, addr);
if(!e) goto abort;
/* Add to the addr2offEntry_map */
MAP_addStrKey(&self->addr2offEntry_map, e->addr, e);
/* Add to the addr.offEntry_map */
MAP_addStrKey(&self->addr.offEntry_map, e->addr, e);
}
OFFENTRY_register(e);
/* Take care of reporting, if necessary */
AddrRPT *ar= MAP_findStrItem(&G.rpt.AddrRPT_map, e->addr);
if(ar)
AddrRPT_addLine(ar, self, lbuf);
{ /* Keep ObsvTpl record of offense line in log file */
ObsvTpl *ot= MAP_findStrItem(&self->addr.obsvTpl_map, e->addr);
if(!ot) {
ObsvTpl_create(ot, self, e->addr);
assert(ot);
MAP_addStrKey(&self->addr.obsvTpl_map, e->addr, ot);
}
ObsvTpl_addObsv(ot, pos, line_len);
}
}
} /* End of line reading loop */
/* Take car of possible address reporting */
unsigned nItems= MAP_numItems(&G.rpt.AddrRPT_map);
if(nItems) { /* Take care of address reports now */
AddrRPT *rtnArr[nItems];
MAP_fetchAllItems(&G.rpt.AddrRPT_map, (void**)rtnArr);
for(unsigned i= 0; i < nItems; ++i) {
AddrRPT *ar= rtnArr[i];
ObsvTpl *ot= MAP_findStrItem(&self->addr.obsvTpl_map, ar->addr);
if(!ot) continue;
ObsvTpl_put_AddrRPT(ot, gzfh, ar);
}
}
rtn= self;
abort:
if(fh) ez_gzclose(fh);
if(gzfh) ez_gzclose(gzfh);
return rtn;
}
@ -145,27 +221,19 @@ LOGFILE_destructor(LOGFILE *self)
* Free resources associated with LOGFILE object.
*/
{
if(self->logFilePath)
free(self->logFilePath);
if(self->logFname)
free(self->logFname);
MAP_clearAndDestroy(&self->addr2offEntry_map, (void*(*)(void*))OFFENTRY_destructor);
MAP_destructor(&self->addr2offEntry_map);
/* Clean up the maps and their contents */
MAP_clearAndDestroy(&self->addr.offEntry_map, (void*(*)(void*))OFFENTRY_destructor);
MAP_destructor(&self->addr.offEntry_map);
MAP_clearAndDestroy(&self->addr.obsvTpl_map, (void*(*)(void*))ObsvTpl_destructor);
MAP_destructor(&self->addr.obsvTpl_map);
return self;
}
void
LOGFILE_set_logFilePath(LOGFILE *self, const char *path)
/******************************************************************
* Set the log file name by making a copy of the path.
*/
{
if(self->logFilePath)
free(self->logFilePath);
self->logFilePath= strdup(path);
}
int
LOGFILE_writeCache(LOGFILE *self, const char *fname)
/******************************************************************
@ -173,13 +241,32 @@ LOGFILE_writeCache(LOGFILE *self, const char *fname)
*/
{
int rc, rtn= -1;
DB *dbh= NULL;
FILE *fh= ez_fopen(fname, "w");
rc= MAP_visitAllEntries(&self->addr2offEntry_map, (int(*)(void*,void*))OFFENTRY_cacheWrite, fh);
/* Writes all OFFENTRY object to fh */
rc= MAP_visitAllEntries(&self->addr.offEntry_map, (int(*)(void*,void*))OFFENTRY_cacheWrite, fh);
if(rc) goto abort;
/* Write RptObj's to database if any exist */
if(MAP_numItems(&self->addr.obsvTpl_map)) {
static char dbFname[PATH_MAX];
snprintf(dbFname, sizeof(dbFname), "%s.db", fname);
ez_db_create(&dbh, NULL, 0);
assert(dbh);
ez_db_open(dbh, NULL, dbFname, NULL, DB_BTREE, DB_CREATE, 0664);
/* This will write all entries in the map do the database */
MAP_visitAllEntries(&self->addr.obsvTpl_map, (int(*)(void*,void*))ObsvTpl_db_put, dbh);
}
rtn= 0;
abort:
if(dbh) ez_db_close(dbh, 0);
if(fh) ez_fclose(fh);
return rtn;
}
@ -190,8 +277,8 @@ LOGFILE_print(LOGFILE *self, FILE *fh)
* Print a human readable representation of *self.
*/
{
ez_fprintf(fh, "LOGFILE %p \"%s\" {\n", self, self->logFilePath);
MAP_visitAllEntries(&self->addr2offEntry_map, (int(*)(void*,void*))OFFENTRY_print, fh);
ez_fprintf(fh, "LOGFILE %p \"%s\" {\n", self, self->logFname);
MAP_visitAllEntries(&self->addr.offEntry_map, (int(*)(void*,void*))OFFENTRY_print, fh);
ez_fprintf(fh, "}\n");
return 0;
@ -200,11 +287,11 @@ LOGFILE_print(LOGFILE *self, FILE *fh)
int
LOGFILE_map_addr(LOGFILE *self, MAP *h_rtnMap)
/********************************************************
* Create a addr2offEntry_map of OFFENTRY objects with composite
* Create a addr.offEntry_map of OFFENTRY objects with composite
* counts by address.
*/
{
MAP_visitAllEntries(&self->addr2offEntry_map, (int(*)(void*,void*))OFFENTRY_map_addr, h_rtnMap);
MAP_visitAllEntries(&self->addr.offEntry_map, (int(*)(void*,void*))OFFENTRY_map_addr, h_rtnMap);
return 0;
}
@ -215,7 +302,7 @@ LOGFILE_offenseCount(LOGFILE *self, unsigned *h_sum)
*/
{
if(!(self->flags & NOFFENSES_CACHED_FLG)) {
MAP_visitAllEntries(&self->addr2offEntry_map, (int(*)(void*,void*))OFFENTRY_offenseCount, &self->nOffenses);
MAP_visitAllEntries(&self->addr.offEntry_map, (int(*)(void*,void*))OFFENTRY_offenseCount, &self->nOffenses);
self->flags |= NOFFENSES_CACHED_FLG;
}
@ -230,7 +317,7 @@ LOGFILE_addressCount(LOGFILE *self, unsigned *h_sum)
* Get a count of all unique addresses for this file.
*/
{
*h_sum += MAP_numItems(&self->addr2offEntry_map);
*h_sum += MAP_numItems(&self->addr.offEntry_map);
return 0;
}

View File

@ -19,6 +19,7 @@
#ifndef LOGFILE_H
#define LOGFILE_H
#define _GNU_SOURCE
#include <stdio.h>
#include "logType.h"
@ -27,32 +28,41 @@
/* One of these for each log file which is scanned. */
typedef struct _LOGFILE {
int flags;
char *logFilePath;
MAP addr2offEntry_map;
char *logFname;
struct {
MAP offEntry_map,
obsvTpl_map;
} addr; /* addr denotes the map keys */
unsigned nOffenses;
} LOGFILE;
#define LOGFILE_logFilePath(self) \
(const char*)(self)->logFilePath
#define LOGFILE_logFname(self) \
(const char*)(self)->logFname
#ifdef __cplusplus
extern "C" {
#endif
#define LOGFILE_cache_create(s, fname) \
((s)=(LOGFILE_cache_constructor((s)=malloc(sizeof(LOGFILE)), fname) ? (s) : ( s ? realloc(LOGFILE_destructor(s),0) : 0 )))
#define LOGFILE_cache_create(s, cacheFname, logFname) \
((s)=(LOGFILE_cache_constructor((s)=malloc(sizeof(LOGFILE)), cacheFname, logFname) ? (s) : ( s ? realloc(LOGFILE_destructor(s),0) : 0 )))
LOGFILE*
LOGFILE_cache_constructor(LOGFILE *self, const char *fname);
LOGFILE_cache_constructor(
LOGFILE *self,
const char *cacheFname,
const char *logFname
);
/******************************************************************
* Initialize an instance of a LOGFILE class.
*/
#define LOGFILE_log_create(s, h_protoType, fname) \
((s)=(LOGFILE_log_constructor((s)=malloc(sizeof(LOGFILE)), h_protoType, fname) ? (s) : ( s ? realloc(LOGFILE_destructor(s),0) : 0 )))
#define LOGFILE_log_create(s, h_protoType, logFname) \
((s)=(LOGFILE_log_constructor((s)=malloc(sizeof(LOGFILE)), h_protoType, logFname) ? (s) : ( s ? realloc(LOGFILE_destructor(s),0) : 0 )))
LOGFILE*
LOGFILE_log_constructor(LOGFILE *self,
const struct logProtoType *h_protoType,
const char *fname);
LOGFILE_log_constructor(
LOGFILE *self,
const struct logProtoType *h_protoType,
const char *logFname
);
/******************************************************************
* Initialize an instance of a LOGFILE class.
*/
@ -65,11 +75,13 @@ LOGFILE_destructor(LOGFILE *self);
* Free resources associated with a LOGFILE object.
*/
#if 0
void
LOGFILE_set_logFilePath(LOGFILE *self, const char *path);
LOGFILE_set_logFname(LOGFILE *self, const char *path);
/******************************************************************
* Set the log file name by making a copy of the path.
*/
#endif
int
LOGFILE_writeCache(LOGFILE *self, const char *fname);

View File

@ -206,14 +206,12 @@ LOGTYPE_proto_constructor(LOGTYPE *self, const struct logProtoType *proto)
LOGFILE *f;
/* Use the cache, if available */
if(!(G.flags & GLB_NO_CACHE_FLG) &&
!access(CacheFname, F_OK))
if(!access(CacheFname, F_OK))
{
/* Construct object from cache file */
LOGFILE_cache_create(f, CacheFname);
LOGFILE_cache_create(f, CacheFname, log_fname);
assert(f);
LOGFILE_set_logFilePath(f, log_fname);
} else { /* Scan the log file, write to new cache */
@ -224,9 +222,7 @@ LOGTYPE_proto_constructor(LOGTYPE *self, const struct logProtoType *proto)
/* Construct object from log file */
LOGFILE_log_create(f, proto, log_fname);
assert(f);
LOGFILE_set_logFilePath(f, log_fname);
if(!(G.flags & GLB_NO_CACHE_FLG) &&
LOGFILE_writeCache(f, CacheFname))
if(LOGFILE_writeCache(f, CacheFname))
{
eprintf("FATAL: write to cache failed.");
exit(EXIT_FAILURE);
@ -263,14 +259,11 @@ LOGTYPE_proto_constructor(LOGTYPE *self, const struct logProtoType *proto)
if(!strcmp(".", entry->d_name) ||
!strcmp("..", entry->d_name)) continue;
LOGFILE *f= MAP_findStrItem(&self->file_map, entry->d_name);
/* Skip all files beginning with the md5 checksum */
LOGFILE *f= MAP_findItem(&self->file_map, entry->d_name, MD5SUM_SZ);
if(f) continue;
rc= snprintf(CacheFname, sizeof(CacheFname), "%s/%s", CacheDname, entry->d_name);
if(sizeof(CacheFname) == rc) {
eprintf("FATAL: File path truncated!");
exit(EXIT_FAILURE);
}
ez_unlink(CacheFname);
}

3
map.c
View File

@ -159,7 +159,8 @@ struct MAP_node *n_ptr;
/* For each node in the bucket... */
PTRVEC_loopFwd(self->bucketArr+ndx, i, n_ptr) {
/* Call the supplied function */
if((*func)(n_ptr->item_ptr, data)) return 1;
int rc= (*func)(n_ptr->item_ptr, data);
if(rc) return rc;
}
}
return 0;

209
obsvTpl.c Normal file
View File

@ -0,0 +1,209 @@
/***************************************************************************
* 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 "ez_libdb.h"
#include "ez_libc.h"
#include "ez_libz.h"
#include "obsvTpl.h"
/* Make sure we don't have padding at the end of this struct */
#pragma pack(push,2)
struct obsv {
z_off_t pos; /* position in the file */
uint16_t len; /* length of string to retrieve */
};
#pragma pack(pop)
ObsvTpl*
ObsvTpl_constructor(ObsvTpl *self, LOGFILE *lf, const char *addr)
/*****************************************************************
* prepare for use.
*/
{
memset(self, 0, sizeof(*self));
strncpy(self->addr, addr, sizeof(self->addr)-1);
self->lf= lf;
DS_constructor(&self->stack, sizeof(struct obsv), 10000);
return self;
}
int
ObsvTpl_sinit(ObsvTpl *self, LOGFILE *lf, const char *addr)
/********************************************************
* Initialize or reset a static instance
*/
{
if(self->lf) {
memset(self->addr, 0, sizeof(self->addr));
strncpy(self->addr, addr, sizeof(self->addr)-1);
self->lf= lf;
DS_reset(&self->stack);
} else {
ObsvTpl_constructor(self, lf, addr);
}
return 0;
}
void*
ObsvTpl_destructor(ObsvTpl *self)
/*****************************************************************
* Free resources
*/
{
DS_destructor(&self->stack);
return self;
}
int
ObsvTpl_addObsv(ObsvTpl *self, z_off_t pos, unsigned len)
/*****************************************************************
* Add an observation to this report object.
*/
{
struct obsv obs;
obs.pos= pos;
obs.len= len;
DS_push(&self->stack, &obs);
return 0;
}
int
ObsvTpl_db_put(ObsvTpl *self, DB *db)
/*****************************************************************
* Write our contents into the database.
*/
{
int rtn= -1;
DBT key= {
.data= self->addr,
.size= strlen(self->addr)
},
data= {
.data= DS_ptr(&self->stack),
.size= DS_numItems(&self->stack) * sizeof(struct obsv)
};
/* Write data to database */
ez_db_put(db, NULL, &key, &data, 0);
rtn= 0;
abort:
return rtn;
}
int
ObsvTpl_db_get(ObsvTpl *self, DB *db)
/********************************************************
* Fetch our content from a database.
*/
{
int rtn= -1;
DBT key= {
.data= self->addr,
.size= strlen(self->addr)
},
data;
memset(&data, 0, sizeof(data));
/* Read from the database */
int rc= ez_db_get(db, NULL, &key, &data, 0);
if(DB_NOTFOUND == rc) return rc;
/* Now put all obsv's in place */
DS_reset(&self->stack);
/* Compute number of items we fetched */
unsigned nItems= data.size / sizeof(struct obsv);
/* Load them into the stack */
for(unsigned i= 0; i < nItems; ++i) {
struct obsv *src= (struct obsv*)data.data + i;
DS_push(&self->stack, src);
}
rtn= 0;
abort:
return rtn;
}
static int obsv_print(struct obsv *self, FILE *fh)
/********************************************************
* Print observation to fh
*/
{
ez_fprintf(fh, "\tpos= %lu, len= %hu\n", (long unsigned)self->pos, self->len);
return 0;
}
int
ObsvTpl_print(ObsvTpl *self, FILE *fh)
/********************************************************
* Print a human readable representation of *self.
*/
{
ez_fprintf(fh, "ObsvTpl %s {\n", self->addr);
DS_visitAllEntries(&self->stack, (int(*)(void*,void*))obsv_print, fh);
ez_fprintf(fh, "}\n");
return 0;
}
struct infoTuple {
gzFile fh;
AddrRPT *ar;
LOGFILE *lf;
};
static int
obsv_load_AddrRPT(struct obsv *self, struct infoTuple *it)
/********************************************************
* load specific observation into it->ar.
*/
{
static char lbuf[1024];
assert(self->len < sizeof(lbuf));
unsigned len= MIN(self->len, sizeof(lbuf)-1);
ez_gzseek(it->fh, self->pos, SEEK_SET);
ez_gzread(it->fh, lbuf, len);
AddrRPT_addLine(it->ar, it->lf, lbuf);
return 0;
}
int
ObsvTpl_put_AddrRPT(ObsvTpl *self, gzFile fh, AddrRPT *ar)
/********************************************************
* Place contents of self into ar.
*/
{
struct infoTuple it= {.fh= fh, .ar= ar, .lf= self->lf};
DS_visitAllEntries(&self->stack, (int(*)(void*,void*))obsv_load_AddrRPT, &it);
return 0;
}

100
obsvTpl.h Normal file
View File

@ -0,0 +1,100 @@
/***************************************************************************
* 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 OBSVTPL_H
#define OBSVTPL_H
#define _GNU_SOURCE
#include <db.h>
#include <stdio.h>
#include <zlib.h>
#include "addrRpt.h"
#include "dynstack.h"
#include "logFile.h"
typedef struct _ObsvTpl {
char addr[43];
LOGFILE *lf;
DS stack;
} ObsvTpl;
#ifdef __cplusplus
extern "C" {
#endif
#define ObsvTpl_create(p, lf, addr) \
((p)=(ObsvTpl_constructor((p)=malloc(sizeof(ObsvTpl)), lf, addr) ? (p) : ( p ? realloc(ObsvTpl_destructor(p),0) : 0 )))
ObsvTpl*
ObsvTpl_constructor(ObsvTpl *self, LOGFILE *lf, const char *addr);
/********************************************************
* Prepare for use from an address on the command line
*/
int
ObsvTpl_sinit(ObsvTpl *self, LOGFILE *lf, const char *addr);
/********************************************************
* Initialize or reset a static instance
*/
#define ObsvTpl_destroy(s) \
{if(ObsvTpl_destructor(s)) {free(s); (s)=0;}}
void*
ObsvTpl_destructor(ObsvTpl *self);
/********************************************************
* Free resources.
*/
int
ObsvTpl_addObsv(ObsvTpl *self, z_off_t pos, unsigned len);
/*****************************************************************
* Add an observation to this object.
*/
int
ObsvTpl_db_get(ObsvTpl *self, DB *db);
/********************************************************
* Fetch our content from a database.
*/
int
ObsvTpl_db_put(ObsvTpl *self, DB *db);
/*****************************************************************
* Write our contents into the database.
*/
int
ObsvTpl_put_AddrRPT(ObsvTpl *self, gzFile fh, AddrRPT *ar);
/********************************************************
* Place contents of self into ar.
*/
int
ObsvTpl_print(ObsvTpl *self, FILE *fh);
/********************************************************
* Print a human readable representation of *self.
*/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -21,14 +21,15 @@
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include "ban2fail.h"
#include "cntry.h"
#include "ez_libdb.h"
#include "ez_libc.h"
#include "map.h"
#include "offEntry.h"
#include "util.h"
/********************************************************/
/**************** OFFENTRY ******************************/
/********************************************************/
@ -167,5 +168,6 @@ OFFENTRY_offenseCount(OFFENTRY *self, unsigned *h_sum)
*/
{
*h_sum += self->count;
//eprintf("%s numItems= %u", self->addr, PTRVEC_numItems(&self->rptObj_vec));
return 0;
}

View File

@ -19,8 +19,10 @@
#ifndef OFFENTRY_H
#define OFFENTRY_H
#define _GNU_SOURCE
#include <stdio.h>
#include <time.h>
#include <zlib.h>
#include "map.h"
#include "pdns.h"
@ -40,6 +42,13 @@ typedef struct _OFFENTRY {
} OFFENTRY;
#if 0
struct OFFENTRY_cacheWrite {
FILE *fh;
DB *dbh;
};
#endif
#ifdef __cplusplus
extern "C" {
#endif