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;
+}
#define MAXGLINEUSERHITS 500
#define MAXGLINECHANNELHITS 50
+#define MAXGLINELOG 500
+
#define GLINE_IGNORE_TRUST 1
#define GLINE_ALWAYS_NICK 2
#define GLINE_ALWAYS_USER 4
} 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 *);
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 *);
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 *);
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "../lib/irc_string.h"
#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;
}
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;
}
/* 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)) {
gl->lastmod = lastmod;
gl->lifetime = lifetime;
- gl->next = gbuf->head;
- gbuf->head = gl;
+ gl->next = gbuf->glines;
+ gbuf->glines = gl;
return gl;
}
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;
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;
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);
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 */
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));
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);
+}
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)) {
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.");
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)) {
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];
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));
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;
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.");
}
deregistercontrolcmd("trustungline", glines_cmdtrustungline);
deregistercontrolcmd("glstats", glines_cmdglstats);
deregistercontrolcmd("glist", glines_cmdglist);
+ deregistercontrolcmd("glinelog", glines_cmdglinelog);
deregistercontrolcmd("syncglines", glines_cmdsyncglines);
deregistercontrolcmd("cleanupglines", glines_cmdcleanupglines);
}