]> jfr.im git - irc/quakenet/newserv.git/commitdiff
Implement gline log.
authorGunnar Beutner <redacted>
Wed, 17 Jul 2013 20:26:09 +0000 (22:26 +0200)
committerGunnar Beutner <redacted>
Wed, 17 Jul 2013 20:26:09 +0000 (22:26 +0200)
--HG--
branch : shroudtrusts

glines/glines.c
glines/glines.h
glines/glines_buf.c
glines/glines_commands.c

index 7e7b3c541e83431be1e50134874e9fa792aebbaa..c728be5a52b9b1d183c86be1ad0ff56918359415 100644 (file)
@@ -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;
+}
index 154de6c94a61830267123cd239d2b35919b4a933..c5e60d07aa7b4f0a380784dc66f537d36e81b3fe 100644 (file)
@@ -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 *);
index d00ee34f8e535f55ab3ea01898295b092884e205..278b3cffe3a687fb399002b57f8babd46b561ba0 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
 #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);
+}
index efc78b97d6181dbc264517764029a5ba30b53ddd..fbda5e52b2382659d6d06cdbf06d672f4efe2e70 100644 (file)
@@ -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> <user>\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] <mask>\nLists matching G-Lines.\nValid flags are:\n-c: Count G-Lines.\n-f: Find G-Lines active on <mask>.\n-x: Find G-Lines matching <mask> 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);
 }