From: Gunnar Beutner Date: Wed, 17 Jul 2013 20:26:09 +0000 (+0200) Subject: Implement gline log. X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/ce11a20097fbc74f15f7180a00014083852bd988 Implement gline log. --HG-- branch : shroudtrusts --- diff --git a/glines/glines.c b/glines/glines.c index 7e7b3c54..c728be5a 100644 --- a/glines/glines.c +++ b/glines/glines.c @@ -396,3 +396,35 @@ int isglinesane(gline *gl, const char **hint) { return 1; } + +gline *glinedup(gline *gl) { + gline *sgl; + + sgl = newgline(); + + if (!sgl) + return NULL; + + if (gl->nick) + sgl->nick = getsstring(gl->nick->content, 512); + + if (gl->user) + sgl->user = getsstring(gl->user->content, 512); + + if (gl->host) + sgl->host = getsstring(gl->host->content, 512); + + sgl->reason = getsstring(gl->reason->content, 512); + sgl->creator = getsstring(gl->creator->content, 512); + + memcpy(&sgl->ip, &gl->ip, sizeof(gl->ip)); + sgl->bits = gl->bits; + + sgl->expire = gl->expire; + sgl->lastmod = gl->lastmod; + sgl->lifetime = gl->lifetime; + + sgl->flags = gl->flags; + + return sgl; +} diff --git a/glines/glines.h b/glines/glines.h index 154de6c9..c5e60d07 100644 --- a/glines/glines.h +++ b/glines/glines.h @@ -16,6 +16,8 @@ #define MAXGLINEUSERHITS 500 #define MAXGLINECHANNELHITS 50 +#define MAXGLINELOG 500 + #define GLINE_IGNORE_TRUST 1 #define GLINE_ALWAYS_NICK 2 #define GLINE_ALWAYS_USER 4 @@ -77,11 +79,17 @@ typedef struct gline { } gline; typedef struct glinebuf { - gline *head; + int id; + sstring *comment; + time_t flush; + + gline *glines; int merge; } glinebuf; extern gline *glinelist; +extern glinebuf *glinebuflog[MAXGLINELOG]; +extern int glinebuflogoffset; /* glines.c */ gline *findgline(const char *); @@ -94,6 +102,7 @@ int gline_match_mask(gline *gla, gline *glb); int gline_match_nick(gline *gl, nick *np); int gline_match_channel(gline *gl, channel *cp); int isglinesane(gline *gl, const char **hint); +gline *glinedup(gline *gl); /* glines_formats.c */ gline *makegline(const char *); @@ -114,6 +123,8 @@ int glinebufchecksane(glinebuf *gbuf, nick *spewto, int overridesanity, int over void glinebufspew(glinebuf *gbuf, nick *spewto); void glinebufflush(glinebuf *gbuf, int propagate); void glinebufabandon(glinebuf *gbuf); +void glinebufcommentf(glinebuf *gbuf, const char *format, ...); +void glinebufcommentv(glinebuf *gbuf, const char *prefix, int cargc, char **cargv); /* glines_alloc.c */ void freegline(gline *); diff --git a/glines/glines_buf.c b/glines/glines_buf.c index d00ee34f..278b3cff 100644 --- a/glines/glines_buf.c +++ b/glines/glines_buf.c @@ -1,3 +1,4 @@ +#include #include #include #include "../lib/irc_string.h" @@ -6,8 +7,14 @@ #include "../trusts/trusts.h" #include "glines.h" +static int nextglinebufid = 1; +glinebuf *glinebuflog[MAXGLINELOG] = {}; +int glinebuflogoffset = 0; + void glinebufinit(glinebuf *gbuf, int merge) { - gbuf->head = NULL; + gbuf->id = 0; + gbuf->comment = NULL; + gbuf->glines = NULL; gbuf->merge = merge; } @@ -24,7 +31,7 @@ gline *glinebufadd(glinebuf *gbuf, const char *mask, const char *creator, const if (gbuf->merge) { /* Check if an existing gline supercedes this mask */ - for (sgl = gbuf->head; sgl; sgl = sgl->next) { + for (sgl = gbuf->glines; sgl; sgl = sgl->next) { if (gline_match_mask(sgl, gl)) { freegline(gl); return sgl; @@ -32,7 +39,7 @@ gline *glinebufadd(glinebuf *gbuf, const char *mask, const char *creator, const } /* Remove older glines this gline matches */ - for (pnext = &gbuf->head; *pnext; pnext = &((*pnext)->next)) { + for (pnext = &gbuf->glines; *pnext; pnext = &((*pnext)->next)) { sgl = *pnext; if (gline_match_mask(gl, sgl)) { @@ -55,8 +62,8 @@ gline *glinebufadd(glinebuf *gbuf, const char *mask, const char *creator, const gl->lastmod = lastmod; gl->lifetime = lifetime; - gl->next = gbuf->head; - gbuf->head = gl; + gl->next = gbuf->glines; + gbuf->glines = gl; return gl; } @@ -124,7 +131,7 @@ void glinebufcounthits(glinebuf *gbuf, int *users, int *channels, nick *spewto) hit = 0; - for (gl = gbuf->head; gl; gl = gl->next) { + for (gl = gbuf->glines; gl; gl = gl->next) { if (gline_match_channel(gl, cp)) { hit = 1; break; @@ -146,7 +153,7 @@ void glinebufcounthits(glinebuf *gbuf, int *users, int *channels, nick *spewto) for (np = nicktable[i]; np; np = np->next) { hit = 0; - for (gl = gbuf->head; gl; gl = gl->next) { + for (gl = gbuf->glines; gl; gl = gl->next) { if (gline_match_nick(gl, np)) { hit = 1; break; @@ -185,7 +192,7 @@ int glinebufchecksane(glinebuf *gbuf, nick *spewto, int overridesanity, int over if (!overridesanity) { /* Remove glines that fail the sanity check */ - for (gl = gbuf->head; gl; gl = gl->next) { + for (gl = gbuf->glines; gl; gl = gl->next) { if (!isglinesane(gl, &hint)) { controlreply(spewto, "Sanity check failed for G-Line on '%s' - Skipping: %s", glinetostring(gl), hint); @@ -199,13 +206,19 @@ int glinebufchecksane(glinebuf *gbuf, nick *spewto, int overridesanity, int over void glinebufspew(glinebuf *gbuf, nick *spewto) { gline *gl; - - for (gl = gbuf->head; gl; gl = gl->next) - controlreply(spewto, "mask: %s", glinetostring(gl)); + time_t ref; + + ref = (gbuf->flush) ? gbuf->flush : getnettime(); + + controlreply(spewto, "Mask Duration Creator Reason"); + + for (gl = gbuf->glines; gl; gl = gl->next) + controlreply(spewto, "%-40s %-20s %-20s %s", glinetostring(gl), longtoduration(gl->expire - ref, 0), gl->creator->content, gl->reason->content); } void glinebufflush(glinebuf *gbuf, int propagate) { gline *gl, *next, *sgl; + glinebuf *gbl; int users, channels; /* Sanity check */ @@ -217,7 +230,19 @@ void glinebufflush(glinebuf *gbuf, int propagate) { return; } - for (gl = gbuf->head; gl; gl = next) { + time(&gbuf->flush); + + if (propagate) { + /* Make a copy of the glinebuf for the log */ + gbl = malloc(sizeof(glinebuf)); + gbl->id = nextglinebufid++; + gbl->comment = (gbuf->comment) ? getsstring(gbuf->comment->content, 512) : NULL; + gbl->flush = gbuf->flush; + gbl->glines = NULL; /* going to set this later */ + gbl->merge = gbuf->merge; + } + + for (gl = gbuf->glines; gl; gl = next) { next = gl->next; sgl = findgline(glinetostring(gl)); @@ -249,17 +274,67 @@ void glinebufflush(glinebuf *gbuf, int propagate) { glinelist = gl; } - if (propagate) + if (propagate) { gline_propagate(gl); + + sgl = glinedup(gl); + sgl->next = gbl->glines; + gbl->glines = sgl; + } + } + + if (propagate && gbl->glines) { + glinebuflogoffset++; + + if (glinebuflogoffset >= MAXGLINELOG) + glinebuflogoffset = 0; + + if (glinebuflog[glinebuflogoffset]) + glinebufabandon(glinebuflog[glinebuflogoffset]); + + glinebuflog[glinebuflogoffset]= gbl; } } void glinebufabandon(glinebuf *gbuf) { gline *gl, *next; - for (gl = gbuf->head; gl; gl = next) { + for (gl = gbuf->glines; gl; gl = next) { next = gl->next; freegline(gl); } } + +void glinebufcommentf(glinebuf *gbuf, const char *format, ...) { + char comment[512]; + va_list va; + + va_start(va, format); + vsnprintf(comment, 511, format, va); + comment[511] = '\0'; + va_end(va); + + gbuf->comment = getsstring(comment, 512); +} + +void glinebufcommentv(glinebuf *gbuf, const char *prefix, int cargc, char **cargv) { + char comment[512]; + int i; + + if (prefix) + strncpy(comment, prefix, sizeof(comment)); + else + comment[0] = '\0'; + + for (i = 0; i < cargc; i++) { + if (comment[0]) + strncat(comment, " ", sizeof(comment)); + + strncat(comment, cargv[i], sizeof(comment)); + } + + comment[511] = '\0'; + + gbuf->comment = getsstring(comment, 512); +} diff --git a/glines/glines_commands.c b/glines/glines_commands.c index efc78b97..fbda5e52 100644 --- a/glines/glines_commands.c +++ b/glines/glines_commands.c @@ -91,6 +91,7 @@ static int glines_cmdblock(void *source, int cargc, char **cargv) { strncpy(creator, controlid(sender), sizeof(creator)); glinebufinit(&gbuf, 1); + glinebufcommentv(&gbuf, "BLOCK", cargc + coff - 1, cargv); glinebufaddbynick(&gbuf, target, 0, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration); if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit, simulate)) { @@ -167,6 +168,7 @@ static int glines_cmdgline(void *source, int cargc, char **cargv) { strncpy(creator, controlid(sender), sizeof(creator)); glinebufinit(&gbuf, 1); + glinebufcommentv(&gbuf, "GLINE", cargc + coff - 1, cargv); if (!glinebufadd(&gbuf, mask, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration)) { controlreply(sender, "Invalid G-Line mask."); @@ -269,6 +271,7 @@ static int glines_cmdsmartgline(void *source, int cargc, char **cargv) { strncpy(creator, controlid(sender), sizeof(creator)); glinebufinit(&gbuf, 1); + glinebufcommentv(&gbuf, "SMARTGLINE", cargc + coff - 1, cargv); glinebufaddbyip(&gbuf, user, &ip, 128, 0, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration); if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit, simulate)) { @@ -432,6 +435,7 @@ static int glines_cmdclearchan(void *source, int cargc, char **cargv) { strncpy(creator, controlid(sender), sizeof(creator)); glinebufinit(&gbuf, 1); + glinebufcommentv(&gbuf, "CLEARCHAN", cargc + coff - 1, cargv); for (i = 0; i < victims.cursi; i++) { np = ((nick **)victims.content)[i]; @@ -535,6 +539,7 @@ static int glines_cmdtrustgline(void *source, int cargc, char **cargv) { strncpy(creator, controlid(sender), sizeof(creator)); glinebufinit(&gbuf, 0); + glinebufcommentv(&gbuf, "TRUSTGLINE", cargc + coff - 1, cargv); for(th = tg->hosts; th; th = th->next) { snprintf(mask, sizeof(mask), "*!%s@%s", cargv[1], trusts_cidr2str(&th->ip, th->bits)); @@ -816,6 +821,56 @@ static int glines_cmdglist(void *source, int cargc, char **cargv) { return CMD_OK; } +static int glines_cmdglinelog(void *source, int cargc, char **cargv) { + nick *sender = source; + glinebuf *gbl; + gline *gl; + int i, id, count; + char timebuf[30]; + + id = 0; + + if (cargc > 0) { + id = atoi(cargv[0]); + + if (id == 0) { + controlreply(sender, "Invalid log ID."); + return CMD_ERROR; + } + } + + for (i = 0; i < MAXGLINELOG; i++) { + gbl = glinebuflog[(i + glinebuflogoffset) % MAXGLINELOG]; + + if (!gbl) + continue; + + if (id == 0 || gbl->id == id) { + count = 0; + + for (gl = gbl->glines; gl; gl = gl->next) + count++; + + strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime(&gbl->flush)); + controlreply(sender, "[%s] ID: %d - %d glines (%s)", timebuf, gbl->id, count, gbl->comment ? gbl->comment->content : "no comment"); + } + + if (id != 0 && gbl->id == id) { + glinebufspew(gbl, sender); + controlreply(sender, "Done."); + return CMD_OK; + } + } + + if (id == 0) { + controlreply(sender, "Done."); + } else { + controlreply(sender, "Log entry for ID %d not found.", id); + } + + return CMD_OK; +} + static int glines_cmdsyncglines(void *source, int cargc, char **cargv) { nick *sender = source; gline *gl; @@ -885,6 +940,7 @@ static void registercommands(int hooknum, void *arg) { registercontrolhelpcmd("trustungline", NO_OPER, 2, glines_cmdtrustungline, "Usage: trustungline <#id|name> \nRemoves a gline that was previously set with trustgline."); registercontrolhelpcmd("glstats", NO_OPER, 0, glines_cmdglstats, "Usage: glstat\nShows statistics about G-Lines."); registercontrolhelpcmd("glist", NO_OPER, 2, glines_cmdglist, "Usage: glist [-flags] \nLists matching G-Lines.\nValid flags are:\n-c: Count G-Lines.\n-f: Find G-Lines active on .\n-x: Find G-Lines matching exactly.\n-R: Find G-lines on realnames.\n-o: Search for glines by owner.\n-r: Search for glines by reason.\n-i: Include inactive glines."); + registercontrolhelpcmd("glinelog", NO_OPER, 1, glines_cmdglinelog, "Usage: glinelog ?id?\nShows information about previous gline transactions."); registercontrolhelpcmd("syncglines", NO_DEVELOPER, 0, glines_cmdsyncglines, "Usage: syncglines\nSends all G-Lines to all other servers."); registercontrolhelpcmd("cleanupglines", NO_DEVELOPER, 0, glines_cmdcleanupglines, "Usage: cleanupglines\nDestroys all deactivated G-Lines."); } @@ -904,6 +960,7 @@ static void deregistercommands(int hooknum, void *arg) { deregistercontrolcmd("trustungline", glines_cmdtrustungline); deregistercontrolcmd("glstats", glines_cmdglstats); deregistercontrolcmd("glist", glines_cmdglist); + deregistercontrolcmd("glinelog", glines_cmdglinelog); deregistercontrolcmd("syncglines", glines_cmdsyncglines); deregistercontrolcmd("cleanupglines", glines_cmdcleanupglines); }