Browse Source

* implement stats() for source modules

master
Alex 'AdUser' Z 4 years ago
parent
commit
119b9a8be4
  1. 70
      src/sources/files.c
  2. 23
      src/sources/portknock.c
  3. 24
      src/sources/redis.c
  4. 8
      src/sources/source.h

70
src/sources/files.c

@ -9,16 +9,17 @@
#include <sys/stat.h>
#include <glob.h>
#include <time.h>
#include "source.h"
#define MODNAME "files"
typedef struct f2b_file_t {
struct f2b_file_t *next;
bool opened;
char path[PATH_MAX];
FILE *fd;
char path[PATH_MAX];
struct stat st;
unsigned int lines;
} f2b_file_t;
struct _config {
@ -32,6 +33,7 @@ struct _config {
static bool
file_open(f2b_file_t *file, const char *path) {
FILE *fd;
struct stat st;
char buf[PATH_MAX] = "";
@ -48,15 +50,17 @@ file_open(f2b_file_t *file, const char *path) {
if (!(S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode)))
return false;
if ((file->fd = fopen(buf, "r")) == NULL)
if ((fd = fopen(buf, "r")) == NULL)
return false;
if (S_ISREG(st.st_mode) && fseek(file->fd, 0, SEEK_END) < 0)
if (S_ISREG(st.st_mode) && fseek(fd, 0, SEEK_END) < 0) {
fclose(fd);
return false;
}
memcpy(&file->st, &st, sizeof(st));
strlcpy(file->path, buf, sizeof(file->path));
file->opened = true;
file->fd = fd;
return true;
}
@ -65,19 +69,21 @@ static void
file_close(f2b_file_t *file) {
assert(file != NULL);
if (file->fd)
fclose(file->fd);
if (file->fd == NULL)
return;
file->opened = false;
fclose(file->fd);
file->fd = NULL;
file->lines = 0;
memset(&file->st, 0, sizeof(struct stat));
}
static bool
file_rotated(const cfg_t *cfg, const f2b_file_t *file) {
file_rotated(const cfg_t *cfg, f2b_file_t *file) {
struct stat st;
assert(file != NULL);
if (!file->opened)
if (file->fd == NULL)
return true;
if (stat(file->path, &st) != 0) {
@ -90,21 +96,25 @@ file_rotated(const cfg_t *cfg, const f2b_file_t *file) {
file->st.st_size > st.st_size) {
log_msg(cfg, info, "file replaced: %s", file->path);
return true;
} else if (file->st.st_size < st.st_size) {
memcpy(&file->st, &st, sizeof(struct stat));
}
return false;
}
static bool
file_getline(const f2b_file_t *file, char *buf, size_t bufsize) {
file_getline(f2b_file_t *file, char *buf, size_t bufsize) {
assert(file != NULL);
assert(buf != NULL);
if (feof(file->fd))
clearerr(file->fd);
/* fread()+EOF set is implementation defined */
if (fgets(buf, bufsize, file->fd) != NULL)
if (fgets(buf, bufsize, file->fd) != NULL) {
file->lines++;
return true;
}
return false;
}
@ -199,7 +209,7 @@ next(cfg_t *cfg, char *buf, size_t bufsize, bool reset) {
for (f2b_file_t *file = cfg->current; file != NULL; file = file->next) {
if (file_rotated(cfg, file))
file_close(file);
if (!file->opened && !file_open(file, NULL)) {
if (file->fd == NULL && !file_open(file, NULL)) {
log_msg(cfg, error, "can't open file: %s", file->path);
continue;
}
@ -210,6 +220,40 @@ next(cfg_t *cfg, char *buf, size_t bufsize, bool reset) {
return false;
}
bool
stats(cfg_t *cfg, char *buf, size_t bufsize) {
struct tm tm;
char tmp[PATH_MAX + 512];
char mtime[30];
const char *fmt =
"- path: %s\n"
" mtime: %s\n"
" fstat: fd=%d inode=%d size=%ld pos=%ld\n"
" read: %lu lines\n";
int fd, ino; off_t sz; long pos;
assert(cfg != NULL);
assert(buf != NULL);
assert(bufsize > 0);
if (buf == NULL || bufsize == 0)
return false;
for (f2b_file_t *f = cfg->files; f != NULL; f = f->next) {
if (f->fd) {
fd = fileno(f->fd), ino = f->st.st_ino, sz = f->st.st_size, pos = ftell(f->fd);
localtime_r(&f->st.st_mtime, &tm);
strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S", &tm);
} else {
fd = -1, ino = -1, sz = 0, pos = -1;
strlcpy(mtime, "-", sizeof(mtime));
}
snprintf(tmp, sizeof(tmp), fmt, f->path, mtime, fd, ino, sz, pos, f->lines);
strlcat(buf, tmp, bufsize);
}
return true;
}
void
destroy(cfg_t *cfg) {
assert(cfg != NULL);

23
src/sources/portknock.c

@ -20,6 +20,7 @@ typedef struct f2b_port_t {
struct f2b_port_t *next;
char host[HOST_MAX];
char port[PORT_MAX];
unsigned int accepts;
int sock;
} f2b_port_t;
@ -188,7 +189,8 @@ next(cfg_t *cfg, char *buf, size_t bufsize, bool reset) {
log_msg(cfg, error, "accept() error: %s", strerror(errno));
continue;
}
close(sock);
port->accepts++;
shutdown(sock, SHUT_RDWR);
if (addr.ss_family == AF_INET) {
inet_ntop(AF_INET, &(((struct sockaddr_in *) &addr)->sin_addr), buf, bufsize);
return true;
@ -203,6 +205,25 @@ next(cfg_t *cfg, char *buf, size_t bufsize, bool reset) {
return false;
}
bool
stats(cfg_t *cfg, char *buf, size_t bufsize) {
char tmp[256];
const char *fmt =
"- listen: %s:%s\n"
" accepts: %u\n";
assert(cfg != NULL);
if (buf == NULL || bufsize == 0)
return false;
for (f2b_port_t *p = cfg->ports; p != NULL; p = p->next) {
snprintf(tmp, sizeof(tmp), fmt, p->host, p->port, p->accepts);
strlcat(buf, tmp, bufsize);
}
return true;
}
void
destroy(cfg_t *cfg) {
f2b_port_t *next;

24
src/sources/redis.c

@ -23,6 +23,7 @@ struct _config {
char password[32];
char host[32];
uint16_t port;
uint32_t received;
redisContext *conn;
};
@ -196,6 +197,7 @@ next(cfg_t *cfg, char *buf, size_t bufsize, bool reset) {
redisReply *reply = NULL;
if (redisGetReply(cfg->conn, (void **) &reply) == REDIS_OK) {
cfg->received++;
if (reply->type == REDIS_REPLY_ARRAY) {
if (strcmp(reply->element[0]->str, "message") == 0 ||
strcmp(reply->element[1]->str, cfg->hash) == 0) {
@ -217,6 +219,28 @@ next(cfg_t *cfg, char *buf, size_t bufsize, bool reset) {
return gotit;
}
bool
stats(cfg_t *cfg, char *buf, size_t bufsize) {
const char *fmt =
"connected: %s\n"
"last error: %d (%s)\n"
"messages: %u\n";
assert(cfg != NULL);
if (buf == NULL || bufsize == 0)
return false;
if (cfg->conn) {
const char *err = cfg->conn->errstr[0] == '\0' ? cfg->conn->errstr : "---";
snprintf(buf, bufsize, fmt, "yes", cfg->conn->err, err, cfg->received);
} else {
snprintf(buf, bufsize, fmt, "no", "0", "---", cfg->received);
}
return true;
}
void
destroy(cfg_t *cfg) {
assert(cfg != NULL);

8
src/sources/source.h

@ -120,6 +120,14 @@ extern bool start(cfg_t *cfg);
* @returns false if no new data available, or true otherwise with filling @a buf
*/
extern bool next(cfg_t *cfg, char *buf, size_t bufsize, bool reset);
/**
* @brief Get statistics for source
* @param cfg Module handler
* @param buf Pointer to buffer for stats report
* @param bufsize Size of buffer above (in bytes)
* @returns true on success, false on error
*/
extern bool stats(cfg_t *cfg, char *buf, size_t bufsize);
/**
* @brief Deallocate resources, prepare for module destroy
* @param cfg Module handler

Loading…
Cancel
Save