#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include "../lib/array.h"
#include "../lib/irc_string.h"
#include "../irc/irc.h"
gbuf->commit = 0;
gbuf->amend = 0;
gbuf->glines = NULL;
- gbuf->hitsvalid = 0;
+ gbuf->hitsvalid = 1;
gbuf->userhits = 0;
gbuf->channelhits = 0;
array_init(&gbuf->hits, sizeof(sstring *));
if (nodebits < bits)
bits = nodebits;
- snprintf(mask, sizeof(mask), "%s@%s", user, trusts_cidr2str(ip, bits));
+ snprintf(mask, sizeof(mask), "%s@%s", user, CIDRtostr(*ip, bits));
glinebufadd(gbuf, mask, creator, reason, expire, lastmod, lifetime);
}
snprintf(mask, sizeof(mask), "%s!*@*", np->nick);
glinebufadd(gbuf, mask, creator, reason, expire, lastmod, lifetime);
} else {
- glinebufaddbyip(gbuf, np->ident, &np->p_ipaddr, 128, flags, creator, reason, expire, lastmod, lifetime);
+ glinebufaddbyip(gbuf, np->ident, &np->ipaddress, 128, flags, creator, reason, expire, lastmod, lifetime);
+ }
+}
+
+void glinebufaddbywhowas(glinebuf *gbuf, whowas *ww, int flags, const char *creator, const char *reason, time_t expire, time_t lastmod, time_t lifetime) {
+ nick *np = &ww->nick;
+
+ if (flags & GLINE_ALWAYS_NICK) {
+ char mask[512];
+ snprintf(mask, sizeof(mask), "%s!*@*", np->nick);
+ glinebufadd(gbuf, mask, creator, reason, expire, lastmod, lifetime);
+ } else {
+ glinebufaddbyip(gbuf, np->ident, &np->ipaddress, 128, flags, creator, reason, expire, lastmod, lifetime);
}
}
void glinebufspew(glinebuf *gbuf, nick *spewto) {
gline *gl;
int i;
- char timebuf[30];
+ char timebuf[30], lastmod[30];
if (!gbuf->hitsvalid)
glinebufcounthits(gbuf, NULL, NULL);
if (gbuf->amend) {
strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime(&gbuf->amend));
- controlreply(spewto, "Ammended at: %s", timebuf);
+ controlreply(spewto, "Amended at: %s", timebuf);
}
- controlreply(spewto, "Mask Duration Last modified Creator Reason");
+ controlreply(spewto, "Mask Expiry Last modified Creator Reason");
for (gl = gbuf->glines; gl; gl = gl->next) {
- strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime(&gl->lastmod));
- controlreply(spewto, "%-40s %-20s %-20s %-20s %s", glinetostring(gl), longtoduration(gl->expire - gl->lastmod, 0), timebuf, gl->creator->content, gl->reason->content);
+ strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime(&gl->expire));
+
+ if (gl->lastmod == 0)
+ strncpy(lastmod, "<ulined>", sizeof(lastmod));
+ else
+ strftime(lastmod, sizeof(lastmod), "%d/%m/%y %H:%M:%S", localtime(&gl->lastmod));
+
+ controlreply(spewto, "%-40s %-20s %-20s %-25s %s", glinetostring(gl), timebuf, lastmod, gl->creator->content, gl->reason ? gl->reason->content : "");
}
controlreply(spewto, "Hits");
break;
}
}
+
+ if (i == 0)
+ controlreply(spewto, "(no hits)");
}
void glinebufmerge(glinebuf *gbuf) {
int glinebufcommit(glinebuf *gbuf, int propagate) {
gline *gl, *next, *sgl;
- glinebuf *gbl;
- int users, channels, i, slot, id;
-
- if (!gbuf->glines)
- return 0; /* Don't waste log IDs on empty gline buffers */
+ int users, channels, id;
/* Sanity check */
glinebufcounthits(gbuf, &users, &channels);
if (propagate && (users > MAXGLINEUSERHITS || channels > MAXGLINECHANNELHITS)) {
- controlwall(NO_OPER, NL_GLINES, "G-Line buffer would hit %d users/%d channels. Not setting G-Lines.");
+ controlwall(NO_OPER, NL_GLINES_AUTO, "G-Line buffer would hit %d users/%d channels. Not setting G-Lines.");
glinebufabort(gbuf);
return 0;
}
+ /* Record the commit time */
time(&gbuf->commit);
- id = 0;
-
- if (propagate) {
- gbl = NULL;
-
- /* Find an existing log buffer */
- if (gbuf->id != 0) {
- for (i = 0; i < MAXGLINELOG; i++) {
- if (!glinebuflog[i])
- continue;
-
- if (glinebuflog[i]->id == gbuf->id) {
- gbl = glinebuflog[i];
- gbl->amend = gbuf->commit;
-
- /* We're going to re-insert this glinebuf, so remove it for now */
- glinebuflog[i] = NULL;
-
- break;
- }
- }
- }
-
- /* Make a new glinebuf for the log */
- if (gbuf->id == 0 || !gbl) {
- gbl = malloc(sizeof(glinebuf));
- gbl->id = (gbuf->id == 0) ? nextglinebufid++ : gbuf->id;
- gbl->comment = (gbuf->comment) ? getsstring(gbuf->comment->content, 512) : NULL;
- gbl->glines = NULL; /* going to set this later */
- gbl->userhits = 0;
- gbl->channelhits = 0;
- gbl->commit = gbuf->commit;
- gbl->amend = 0;
-
- array_init(&gbl->hits, sizeof(sstring *));
- }
-
- gbl->userhits += gbuf->userhits;
- gbl->channelhits += gbuf->channelhits;
-
- for (i = 0; i < gbuf->hits.cursi; i++) {
- slot = array_getfreeslot(&gbl->hits);
- ((sstring **)gbl->hits.content)[slot] = getsstring(((sstring **)gbuf->hits.content)[i]->content, 512);
- }
-
- id = gbl->id;
- }
+ id = glinebufwritelog(gbuf, propagate);
/* Move glines to the global gline list */
for (gl = gbuf->glines; gl; gl = next) {
glinelist = gl;
}
- if (propagate) {
- gline_propagate(gl);
+ gl->glinebufid = id;
- sgl = glinedup(gl);
- sgl->next = gbl->glines;
- gbl->glines = sgl;
- }
+ if (propagate)
+ gline_propagate(gl);
}
/* We've moved all glines to the global gline list. Clear glines link in the glinebuf. */
gbuf->glines = NULL;
- if (propagate && gbl->glines) {
- glinebuflogoffset++;
-
- if (glinebuflogoffset >= MAXGLINELOG)
- glinebuflogoffset = 0;
-
- if (glinebuflog[glinebuflogoffset])
- glinebufabort(glinebuflog[glinebuflogoffset]);
-
- glinebuflog[glinebuflogoffset]= gbl;
- }
-
glinebufabort(gbuf);
return id;
if (!sgl)
continue;
-
+
+ sgl->glinebufid = 0;
+
gline_deactivate(sgl, 0, 1);
}
gbuf->comment = getsstring(comment, 512);
}
+
+int glinebufwritelog(glinebuf *gbuf, int propagating) {
+ int i, slot;
+ gline *gl, *sgl;
+ glinebuf *gbl;
+
+ if (!gbuf->glines)
+ return 0; /* Don't waste log IDs on empty gline buffers */
+
+ gbl = NULL;
+
+ /* Find an existing log buffer with the same id */
+ if (gbuf->id != 0) {
+ for (i = 0; i < MAXGLINELOG; i++) {
+ if (!glinebuflog[i])
+ continue;
+
+ if (glinebuflog[i]->id == gbuf->id) {
+ gbl = glinebuflog[i];
+ gbl->amend = gbuf->commit;
+
+ /* We're going to re-insert this glinebuf, so remove it for now */
+ glinebuflog[i] = NULL;
+
+ break;
+ }
+ }
+ }
+
+ /* Find a recent glinebuf that's a close match */
+ if (!gbl && !propagating) {
+ for (i = 0; i < MAXGLINELOG; i++) {
+ if (!glinebuflog[i])
+ continue;
+
+ if (glinebuflog[i]->commit < getnettime() - 5 && glinebuflog[i]->amend < getnettime() - 5)
+ continue;
+
+ assert(glinebuflog[i]->glines);
+
+ if (strcmp(glinebuflog[i]->glines->creator->content, gbuf->glines->creator->content) != 0)
+ continue;
+
+ gbl = glinebuflog[i];
+ gbl->amend = gbuf->commit;
+
+ /* We're going to re-insert this glinebuf, so remove it for now */
+ glinebuflog[i] = NULL;
+
+ break;
+ }
+ }
+
+ /* Make a new glinebuf for the log */
+ if (!gbl && gbuf->id == 0) {
+ gbl = malloc(sizeof(glinebuf));
+ glinebufinit(gbl, (gbuf->id == 0) ? nextglinebufid++ : gbuf->id);
+
+ assert(gbl->hitsvalid);
+
+ if (gbuf->comment)
+ glinebufcommentf(gbl, "%s", gbuf->comment->content);
+ else if (!propagating)
+ glinebufcommentf(gbl, "G-Lines set by %s", gbuf->glines->creator->content);
+
+ gbl->commit = gbuf->commit;
+ }
+
+ /* Save a duplicate of the glines in the log buffer */
+ for (gl = gbuf->glines; gl; gl = gl->next) {
+ sgl = glinedup(gl);
+ sgl->next = gbl->glines;
+ gbl->glines = sgl;
+ }
+
+ gbl->userhits += gbuf->userhits;
+ gbl->channelhits += gbuf->channelhits;
+
+ assert(gbuf->userhits + gbuf->channelhits == gbuf->hits.cursi);
+
+ for (i = 0; i < gbuf->hits.cursi; i++) {
+ slot = array_getfreeslot(&gbl->hits);
+ ((sstring **)gbl->hits.content)[slot] = getsstring(((sstring **)gbuf->hits.content)[i]->content, 512);
+ }
+
+ /* Log the transaction */
+ glinebuflogoffset++;
+
+ if (glinebuflogoffset >= MAXGLINELOG)
+ glinebuflogoffset = 0;
+
+ if (glinebuflog[glinebuflogoffset])
+ glinebufabort(glinebuflog[glinebuflogoffset]);
+
+ glinebuflog[glinebuflogoffset] = gbl;
+
+ return gbl->id;
+}