Alex 'AdUser' Z
8 years ago
2 changed files with 154 additions and 0 deletions
@ -0,0 +1,127 @@
|
||||
/* Copyright 2016 Alex 'AdUser' Z (ad_user@runbox.com)
|
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 as |
||||
* published by the Free Software Foundation. |
||||
*/ |
||||
|
||||
#include "common.h" |
||||
#include "log.h" |
||||
#include "ipaddr.h" |
||||
#include "statefile.h" |
||||
|
||||
f2b_statefile_t * |
||||
f2b_statefile_create(const char *statedir, const char *jailname) { |
||||
f2b_statefile_t *sf = NULL; |
||||
char path[PATH_MAX]; |
||||
|
||||
assert(statedir != NULL); |
||||
assert(jailname != NULL); |
||||
|
||||
snprintf(path, sizeof(path), "%s/%s.state", statedir, jailname); |
||||
|
||||
if (access(path, R_OK | W_OK) < 0) { |
||||
if (errno != ENOENT) { |
||||
f2b_log_msg(log_error, "can't access statefile: %s", strerror(errno)); |
||||
return NULL; |
||||
} |
||||
int fd = open(path, O_CREAT | O_WRONLY); |
||||
if (fd < 0) { |
||||
f2b_log_msg(log_error, "can't create statefile: %s", strerror(errno)); |
||||
return NULL; |
||||
} |
||||
close(fd); |
||||
} |
||||
|
||||
if ((sf = calloc(1, sizeof(f2b_statefile_t))) == NULL) { |
||||
f2b_log_msg(log_error, "can't allocate memory for statefile: %s", strerror(errno)); |
||||
return NULL; |
||||
} |
||||
|
||||
strlcpy(sf->path, path, sizeof(sf->path)); |
||||
|
||||
return sf; |
||||
} |
||||
|
||||
void |
||||
f2b_statefile_destroy(f2b_statefile_t *sf) { |
||||
if (!sf) return; |
||||
free(sf); |
||||
} |
||||
|
||||
f2b_ipaddr_t * |
||||
f2b_statefile_load(f2b_statefile_t *sf, size_t matches) { |
||||
const int fields = 3; |
||||
const char *format = "%48s %lu %lu"; /* 48 == IPADDR_MAX == sizeof(addr) */ |
||||
f2b_ipaddr_t *addrlist = NULL, *ipaddr = NULL; |
||||
char buf[256], addr[IPADDR_MAX], *p; |
||||
int banned, release; |
||||
FILE *f = NULL; |
||||
|
||||
assert(sf != NULL); |
||||
|
||||
if ((f = fopen(sf->path, "r")) == NULL) { |
||||
f2b_log_msg(log_error, "can't open statefile: %s", strerror(errno)); |
||||
return NULL; |
||||
} |
||||
|
||||
while(fgets(buf, sizeof(buf), f)) { |
||||
p = &buf[0]; |
||||
while(isspace(*p)) |
||||
p++; /* skip leading spaces */ |
||||
if (*p == '#') |
||||
continue; /* is comment */ |
||||
if (sscanf(buf, format, addr, &banned, &release) != fields) { |
||||
f2b_log_msg(log_warn, "can't parse, ignoring line: %s", buf); |
||||
continue; |
||||
} |
||||
if ((ipaddr = f2b_ipaddr_create(addr, matches)) == NULL) { |
||||
f2b_log_msg(log_warn, "can't parse addr: %s", addr); |
||||
continue; |
||||
} |
||||
ipaddr->banned = true; |
||||
ipaddr->banned_at = banned; |
||||
ipaddr->release_at = release; |
||||
ipaddr->next = addrlist; |
||||
addrlist = ipaddr; |
||||
} |
||||
|
||||
fclose(f); |
||||
return addrlist; |
||||
} |
||||
|
||||
bool |
||||
f2b_statefile_save(f2b_statefile_t *sf, f2b_ipaddr_t *addrlist) { |
||||
const char *fmt = "%s\t%lu\t%lu\n"; |
||||
char path[PATH_MAX]; |
||||
FILE *f = NULL; |
||||
|
||||
assert(sf != NULL); |
||||
|
||||
if (addrlist == NULL) |
||||
return true; |
||||
|
||||
strlcpy(path, sf->path, sizeof(path)); |
||||
strlcat(path, ".new", sizeof(path)); |
||||
|
||||
if ((f = fopen(path, "w")) == NULL) { |
||||
f2b_log_msg(log_error, "can't open statefile: %s", strerror(errno)); |
||||
return false; |
||||
} |
||||
|
||||
fprintf(f, "# address\tbanned_at\trelease_at\n"); |
||||
for (f2b_ipaddr_t *ipaddr = addrlist; ipaddr != NULL; ipaddr = ipaddr->next) { |
||||
if (!ipaddr->banned) |
||||
continue; |
||||
fprintf(f, fmt, ipaddr->text, ipaddr->banned_at, ipaddr->release_at); |
||||
} |
||||
fclose(f); |
||||
|
||||
if (rename(path, sf->path) < 0) { |
||||
f2b_log_msg(log_error, "can't replace statefile %s: %s", sf->path, strerror(errno)); |
||||
return false; |
||||
} |
||||
|
||||
sf->need_save = false; |
||||
return true; |
||||
} |
@ -0,0 +1,27 @@
|
||||
/* Copyright 2016 Alex 'AdUser' Z (ad_user@runbox.com)
|
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License version 2 as |
||||
* published by the Free Software Foundation. |
||||
*/ |
||||
#ifndef F2B_STATEFILE_H_ |
||||
#define F2B_STATEFILE_H_ |
||||
|
||||
typedef struct f2b_statefile_t { |
||||
char path[PATH_MAX]; |
||||
bool need_save; |
||||
} f2b_statefile_t; |
||||
|
||||
f2b_statefile_t * |
||||
f2b_statefile_create(const char *statedir, const char *jailname); |
||||
|
||||
void |
||||
f2b_statefile_destroy(f2b_statefile_t *sf); |
||||
|
||||
f2b_ipaddr_t * |
||||
f2b_statefile_load(f2b_statefile_t *sf, size_t matches); |
||||
|
||||
bool |
||||
f2b_statefile_save(f2b_statefile_t *sf, f2b_ipaddr_t *addrlist); |
||||
|
||||
#endif /* F2B_STATEFILE_H_ */ |
Loading…
Reference in new issue