static void registercommands(int, void *);
static void deregistercommands(int, void *);
-static int parse_gline_flags(nick *sender, const char *flagparam, int *overridesanity, int *overridelimit, int *simulate, int *coff) {
+static int parse_gline_flags(nick *sender, const char *flagparam, int *overridesanity, int *overridelimit, int *simulate, int *chase, int *coff) {
const char *pos;
*coff = 0;
*overridelimit = 0;
*simulate = 0;
+ if (chase)
+ *chase = 0;
+
if (flagparam[0] == '-') {
*coff = 1;
case 'S':
*simulate = 1;
break;
+ case 'c':
+ if (!chase)
+ goto invalid;
+
+ *chase = 1;
+ break;
default:
- controlreply(sender, "Invalid flag specified: %c", *pos);
- return 0;
+ goto invalid;
}
}
}
return 1;
+
+invalid:
+ controlreply(sender, "Invalid flag specified: %c", *pos);
+ return 0;
}
static int glines_cmdblock(void *source, int cargc, char **cargv) {
nick *sender = source;
- nick *target;
- int hits, duration;
- int coff, overridesanity, overridelimit, simulate;
+ nick *target, *wnp;
+ whowas *ww;
+ int hits, duration, id;
+ int coff, overridesanity, overridelimit, simulate, chase;
char *reason;
char creator[128];
glinebuf gbuf;
+ int ownww;
if (cargc < 1)
return CMD_USAGE;
- if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, &coff))
+ if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, &chase, &coff))
return CMD_ERROR;
if (cargc < 3 + coff)
return CMD_USAGE;
+ duration = durationtolong(cargv[coff + 1]);
+
+ if (duration <= 0) {
+ controlreply(sender, "Invalid duration specified.");
+ return CMD_ERROR;
+ }
+
target = getnickbynick(cargv[coff]);
if (!target) {
- controlreply(sender, "Sorry, couldn't find that user.");
- return CMD_ERROR;
+ ww = whowas_chase(cargv[coff], 1800);
+
+ if (!ww) {
+ controlreply(sender, "Sorry, couldn't find that user.");
+ return CMD_ERROR;
+ }
+
+ ownww = 0;
+
+ controlreply(sender, "Found matching whowas record:");
+ controlreply(sender, "%s", whowas_format(ww));
+ } else {
+ ww = whowas_fromnick(target, 1);
+ ownww = 1;
}
- duration = durationtolong(cargv[coff + 1]);
+ wnp = &ww->nick;
- if (duration <= 0) {
- controlreply(sender, "Invalid duration specified.");
+ if (sender != target && (IsService(wnp) || IsOper(wnp) || NickOnServiceServer(wnp))) {
+ controlreply(sender, "Target user '%s' is an oper or a service. Not setting G-Lines.", wnp->nick);
return CMD_ERROR;
}
rejoinline(cargv[coff + 2], cargc - coff - 2);
reason = cargv[coff + 2];
- if (sender->auth)
- snprintf(creator, sizeof(creator), "#%s", sender->authname);
- else
- strncpy(creator, controlid(sender), sizeof(creator));
+ snprintf(creator, sizeof(creator), "#%s", sender->authname);
- glinebufinit(&gbuf, 1);
+ glinebufinit(&gbuf, 0);
glinebufcommentv(&gbuf, "BLOCK", cargc + coff - 1, cargv);
- glinebufaddbynick(&gbuf, target, 0, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration);
+ glinebufaddbywhowas(&gbuf, ww, 0, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration);
+
+ glinebufspew(&gbuf, sender);
- if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit, simulate)) {
+ if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) {
glinebufabort(&gbuf);
+ if (ownww)
+ whowas_free(ww);
controlreply(sender, "G-Lines failed sanity checks. Not setting G-Lines.");
return CMD_ERROR;
}
if (simulate) {
glinebufabort(&gbuf);
+ if (ownww)
+ whowas_free(ww);
controlreply(sender, "Simulation complete. Not setting G-Lines.");
return CMD_ERROR;
}
- glinebufcounthits(&gbuf, &hits, NULL, NULL);
- glinebufcommit(&gbuf, 1);
+ glinebufcounthits(&gbuf, &hits, NULL);
+ id = glinebufcommit(&gbuf, 1);
- controlwall(NO_OPER, NL_GLINES, "%s BLOCK'ed user '%s!%s@%s' for %s with reason '%s' (%d hits)", controlid(sender), target->nick, target->ident, target->host->name->content, longtoduration(duration, 0), reason, hits);
+ controlwall(NO_OPER, NL_GLINES, "%s BLOCK'ed user '%s!%s@%s' for %s with reason '%s' (%d hits)", controlid(sender),
+ wnp->nick, wnp->ident, wnp->host->name->content,
+ longtoduration(duration, 0), reason, hits);
- controlreply(sender, "Done.");
+ if (ownww)
+ whowas_free(ww);
+
+ controlreply(sender, "Done. G-Line transaction ID: %d", id);
return CMD_OK;
}
static int glines_cmdgline(void *source, int cargc, char **cargv) {
nick *sender = source;
- int duration, users, channels;
+ int duration, users, channels, id;
char *mask, *reason;
char creator[128];
int coff, overridesanity, overridelimit, simulate;
if (cargc < 1)
return CMD_USAGE;
- if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, &coff))
+ if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, NULL, &coff))
return CMD_ERROR;
if (cargc < 3 + coff)
}
#endif /* SNIRCD_VERSION */
- if (sender->auth)
- snprintf(creator, sizeof(creator), "#%s", sender->authname);
- else
- strncpy(creator, controlid(sender), sizeof(creator));
+ snprintf(creator, sizeof(creator), "#%s", sender->authname);
- glinebufinit(&gbuf, 1);
+ glinebufinit(&gbuf, 0);
glinebufcommentv(&gbuf, "GLINE", cargc + coff - 1, cargv);
if (!glinebufadd(&gbuf, mask, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration)) {
return CMD_ERROR;
}
- if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit, simulate)) {
+ glinebufspew(&gbuf, sender);
+
+ if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) {
glinebufabort(&gbuf);
controlreply(sender, "G-Lines failed sanity checks. Not setting G-Lines.");
return CMD_ERROR;
return CMD_ERROR;
}
- glinebufcounthits(&gbuf, &users, &channels, NULL);
- glinebufcommit(&gbuf, 1);
+ glinebufcounthits(&gbuf, &users, &channels);
+ id = glinebufcommit(&gbuf, 1);
controlwall(NO_OPER, NL_GLINES, "%s GLINE'd mask '%s' for %s with reason '%s' (hits %d users/%d channels)",
controlid(sender), mask, longtoduration(duration, 0), reason, users, channels);
- controlreply(sender, "Done.");
+ controlreply(sender, "Done. G-Line transaction ID: %d", id);
return CMD_OK;
}
struct irc_in_addr ip;
unsigned char bits;
int hits, duration;
- int coff, overridesanity, overridelimit, simulate;
+ int coff, overridesanity, overridelimit, simulate, id;
char *reason;
char creator[128];
glinebuf gbuf;
if (cargc < 1)
return CMD_USAGE;
- if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, &coff))
+ if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, NULL, &coff))
return CMD_ERROR;
if (cargc < 3 + coff)
return CMD_ERROR;
}
- if (sender->auth)
- snprintf(creator, sizeof(creator), "#%s", sender->authname);
- else
- strncpy(creator, controlid(sender), sizeof(creator));
+ snprintf(creator, sizeof(creator), "#%s", sender->authname);
- glinebufinit(&gbuf, 1);
+ glinebufinit(&gbuf, 0);
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)) {
+ glinebufspew(&gbuf, sender);
+
+ if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) {
glinebufabort(&gbuf);
controlreply(sender, "G-Lines failed sanity checks. Not setting G-Lines.");
return CMD_ERROR;
return CMD_ERROR;
}
- glinebufcounthits(&gbuf, &hits, NULL, NULL);
- glinebufcommit(&gbuf, 1);
+ glinebufcounthits(&gbuf, &hits, NULL);
+ id = glinebufcommit(&gbuf, 1);
controlwall(NO_OPER, NL_GLINES, "%s SMARTGLINE'd mask '%s' for %s with reason '%s' (%d hits)",
controlid(sender), cargv[0], longtoduration(duration, 0), reason, hits);
- controlreply(sender, "Done.");
+ controlreply(sender, "Done. G-Line transaction ID: %d", id);
return CMD_OK;
}
channel *cp;
nick *np;
char *reason = "Clearing channel.";
- int mode, duration, i, slot, hits;
+ int mode, duration, i, slot, hits, id;
int coff, overridesanity, overridelimit, simulate;
array victims;
char creator[128];
if (cargc < 1)
return CMD_USAGE;
- if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, &coff))
+ if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, NULL, &coff))
return CMD_ERROR;
if (cargc < 2 + coff)
(((nick **)victims.content)[slot]) = np;
}
- if (sender->auth)
- snprintf(creator, sizeof(creator), "#%s", sender->authname);
- else
- strncpy(creator, controlid(sender), sizeof(creator));
+ snprintf(creator, sizeof(creator), "#%s", sender->authname);
- glinebufinit(&gbuf, 1);
+ glinebufinit(&gbuf, 0);
glinebufcommentv(&gbuf, "CLEARCHAN", cargc + coff - 1, cargv);
for (i = 0; i < victims.cursi; i++) {
}
}
- if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit, simulate)) {
- glinebufabort(&gbuf);
- controlreply(sender, "G-Line failed sanity checks. Not setting G-Line.");
- return CMD_ERROR;
+ if (mode != 0 && mode != 1) {
+ glinebufspew(&gbuf, sender);
+
+ if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) {
+ glinebufabort(&gbuf);
+ controlreply(sender, "G-Line failed sanity checks. Not setting G-Line.");
+ return CMD_ERROR;
+ }
}
if (simulate) {
return CMD_ERROR;
}
- glinebufcounthits(&gbuf, &hits, NULL, NULL);
- glinebufcommit(&gbuf, 1);
+ glinebufmerge(&gbuf);
+ glinebufcounthits(&gbuf, &hits, NULL);
+ id = glinebufcommit(&gbuf, 1);
array_free(&victims);
- if (mode == 0 || mode == 1)
+ if (mode == 0 || mode == 1) {
controlwall(NO_OPER, NL_GLINES, "%s CLEARCHAN'd channel '%s' with mode '%s' and reason '%s'",
controlid(sender), cp->index->name->content, cargv[1], reason);
- else
+ controlreply(sender, "Done.");
+ } else {
controlwall(NO_OPER, NL_GLINES, "%s CLEARCHAN'd channel '%s' with mode '%s', duration %s and reason '%s' (%d hits)",
controlid(sender), cp->index->name->content, cargv[1], longtoduration(duration, 0), reason, hits);
-
- controlreply(sender, "Done.");
+ controlreply(sender, "Done. G-Line transaction ID: %d", id);
+ }
return CMD_OK;
}
trustgroup *tg;
trusthost *th;
int duration, hits;
- int coff, overridesanity, overridelimit, simulate;
+ int coff, overridesanity, overridelimit, simulate, id;
char *reason;
char mask[512];
char creator[128];
if (cargc < 1)
return CMD_USAGE;
- if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, &coff))
+ if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, NULL, &coff))
return CMD_ERROR;
if (cargc < 4 + coff)
rejoinline(cargv[coff + 3], cargc - coff - 3);
reason = cargv[coff + 3];
- if (sender->auth)
- snprintf(creator, sizeof(creator), "#%s", sender->authname);
- else
- strncpy(creator, controlid(sender), sizeof(creator));
+ snprintf(creator, sizeof(creator), "#%s", sender->authname);
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));
+ snprintf(mask, sizeof(mask), "*!%s@%s", cargv[1], CIDRtostr(th->ip, th->bits));
glinebufadd(&gbuf, mask, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration);
}
- if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit, simulate)) {
+ glinebufspew(&gbuf, sender);
+
+ if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) {
glinebufabort(&gbuf);
controlreply(sender, "G-Line failed sanity checks. Not setting G-Line.");
return CMD_ERROR;
return CMD_ERROR;
}
- glinebufcounthits(&gbuf, &hits, NULL, NULL);
- glinebufcommit(&gbuf, 1);
+ glinebufcounthits(&gbuf, &hits, NULL);
+ id = glinebufcommit(&gbuf, 1);
controlwall(NO_OPER, NL_GLINES, "%s TRUSTGLINE'd user '%s' on trust group '%s' for %s with reason '%s' (%d hits)",
controlid(sender), cargv[1], tg->name->content, longtoduration(duration, 0), reason, hits);
- controlreply(sender, "Done.");
+ controlreply(sender, "Done. G-Line transaction ID: %d", id);
return CMD_OK;
}
count = 0;
for (th = tg->hosts; th; th = th->next) {
- snprintf(mask, sizeof(mask), "*!%s@%s", cargv[1], trusts_cidr2str(&th->ip, th->bits));
+ snprintf(mask, sizeof(mask), "*!%s@%s", cargv[1], CIDRtostr(th->ip, th->bits));
gl = findgline(mask);
char *mask;
int count = 0;
int limit = 500;
- char tmp[250];
+ char expirestr[250], idstr[250];
if (cargc < 1 || (cargc == 1 && cargv[0][0] == '-')) {
controlreply(sender, "Syntax: glist [-flags] <mask>");
return CMD_ERROR;
}
- mask = cargv[0];
-
if (cargc > 1) {
char* ch = cargv[0];
}
if (!(flags & GLIST_COUNT))
- controlreply(sender, "%-50s %-19s %-25s %s", "Mask:", "Expires in:", "Creator:", "Reason:");
+ controlreply(sender, "%-50s %-19s %-15s %-25s %s", "Mask:", "Expires in:", "Transaction ID:", "Creator:", "Reason:");
gline *searchgl = makegline(mask);
+ if (!searchgl) {
+ controlreply(sender, "Invalid G-line mask specified.");
+ return CMD_ERROR;
+ }
+
for (gl = glinelist; gl; gl = next) {
next = gl->next;
if (!(gl->flags & GLINE_REALNAME))
continue;
if (flags & GLIST_EXACT) {
- if (!glineequal(searchgl, gl)) {
+ if (!glineequal(searchgl, gl))
continue;
- }
} else if (flags & GLIST_FIND) {
- if (!gline_match_mask(searchgl, gl)) {
+ if (!gline_match_mask(gl, searchgl))
+ continue;
+ } else {
+ if (!match2strings(mask, glinetostring(gl)))
continue;
- }
}
} else {
if (gl->flags & GLINE_REALNAME)
if (!gl->reason || ircd_strcmp(mask, gl->reason->content) != 0)
continue;
} else if (flags & GLIST_FIND) {
- if (!gl->reason || match(gl->reason->content, mask))
+ if (!gl->reason || !match2strings(gl->reason->content, mask))
continue;
- } else if (!gl->reason || match(mask, gl->reason->content))
+ } else if (!gl->reason || !match2strings(mask, gl->reason->content))
continue;
} else if (flags & GLIST_OWNER) {
if (flags & GLIST_EXACT) {
if (!gl->creator || ircd_strcmp(mask, gl->creator->content) != 0)
continue;
} else if (flags & GLIST_FIND) {
- if (!gl->creator || match(gl->creator->content, mask))
+ if (!gl->creator || !match2strings(gl->creator->content, mask))
continue;
- } else if (!gl->creator || match(mask, gl->creator->content))
+ } else if (!gl->creator || !match2strings(mask, gl->creator->content))
continue;
} else {
if (flags & GLIST_EXACT) {
- if (!glineequal(searchgl, gl)) {
+ if (!glineequal(searchgl, gl))
continue;
- }
} else if (flags & GLIST_FIND) {
- if (!gline_match_mask(searchgl, gl)) {
+ if (!gline_match_mask(gl, searchgl))
+ continue;
+ } else {
+ if (!match2strings(mask, glinetostring(gl)))
continue;
- }
}
}
}
count++;
if (!(flags & GLIST_COUNT) && count < limit) {
- snprintf(tmp, 249, "%s", glinetostring(gl));
- controlreply(sender, "%s%-49s %-19s %-25s %s",
+ snprintf(expirestr, sizeof(expirestr), "%s", glinetostring(gl));
+ snprintf(idstr, sizeof(idstr), "%d", gl->glinebufid);
+ controlreply(sender, "%s%-49s %-19s %-15s %-25s %s",
(gl->flags & GLINE_ACTIVE) ? "+" : "-",
- tmp,
+ expirestr,
(gl->flags & GLINE_ACTIVE) ? (char*)longtoduration(gl->expire - curtime, 0) : "<inactive>",
+ gl->glinebufid ? idstr : "",
gl->creator ? gl->creator->content : "",
gl->reason ? gl->reason->content : "");
}
for (gl = gbl->glines; gl; gl = gl->next)
count++;
- strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime(&gbl->flush));
- controlreply(sender, "%-20s %-10d %-10d %-15d %-15d %s", timebuf, gbl->id, count, gbl->userhits, gbl->channelhits, gbl->comment ? gbl->comment->content : "no comment");
+ strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime((gbl->amend) ? &gbl->amend : &gbl->commit));
+ strncat(timebuf, (gbl->amend) ? "*" : " ", sizeof(timebuf));
+ controlreply(sender, "%-20s %-10d %-10d %-15d %-15d %s", timebuf, gbl->id, count, gbl->userhits, gbl->channelhits, gbl->comment ? gbl->comment->content : "(no comment)");
}
if (id != 0 && gbl->id == id) {
return;
commandsregistered = 1;
- registercontrolhelpcmd("block", NO_OPER, 4, glines_cmdblock, "Usage: block ?flags? <nick> <duration> <reason>\nSets a gline using an appropriate mask given the user's nickname.\nFlags can be one or more of:\n-f - bypass sanity checks\n-l - bypass hit limits\n-S - simulate who the glines would hit");
+ registercontrolhelpcmd("block", NO_OPER, 4, glines_cmdblock, "Usage: block ?flags? <nick> <duration> <reason>\nSets a gline using an appropriate mask given the user's nickname.\nFlags can be one or more of:\n-f - bypass sanity checks\n-l - bypass hit limits\n-S - simulate who the glines would hit\n-c - chase nick across quits/kills/nick changes");
registercontrolhelpcmd("gline", NO_OPER, 4, glines_cmdgline, "Usage: gline ?flags? <mask> <duration> <reason>\nSets a gline.\nFlags can be one or more of:\n-f - bypass sanity checks\n-l - bypass hit limits\n-S - simulate who the glines would hit");
registercontrolhelpcmd("smartgline", NO_OPER, 4, glines_cmdsmartgline, "Usage: smartgline ?flags? <user@host> <duration> <reason>\nSets a gline. Automatically adjusts the mask depending on whether the specified mask is trusted.\nFlags can be one or more of:\n-f - bypass sanity checks\n-l - bypass hit limits\n-S - simulate who the glines would hit");
registercontrolhelpcmd("ungline", NO_OPER, 1, glines_cmdungline, "Usage: ungline <mask>\nDeactivates a gline.");