X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/61d7d5113a54f5a7fb0b3b320a44d58ad560531e..4b40d278ce1946afc0d942a5acbcd09da68104aa:/trusts/trusts_commands.c diff --git a/trusts/trusts_commands.c b/trusts/trusts_commands.c index 17b29af4..820a4a60 100644 --- a/trusts/trusts_commands.c +++ b/trusts/trusts_commands.c @@ -1,124 +1,330 @@ +#include +#include +#include "../lib/version.h" #include "../control/control.h" #include "../lib/irc_string.h" +#include "../lib/strlfunc.h" +#include "../core/nsmalloc.h" +#include "../irc/irc.h" +#include "../newsearch/newsearch.h" +#include "../glines/glines.h" #include "trusts.h" +#include "newsearch/trusts_newsearch.h" + +MODULE_VERSION(""); -int trusts_migration_start(TrustDBMigrationCallback, void *); -void trusts_migration_stop(void); static void registercommands(int, void *); static void deregistercommands(int, void *); -static void migrate_status(int errcode, void *tag) { - long sender = (long)tag; - nick *np = getnickbynumeric(sender); +extern void printnick_channels(searchCtx *, nick *, nick *); - if(!np) - return; +void calculatespaces(int spaces, int width, const char *str, char **_prebuf, char **_postbuf) { + static char prebuf[512], postbuf[512]; + int spacelen; - if(!errcode || errcode == MIGRATION_LASTERROR) { - if(!errcode) { - controlreply(np, "Migration complete."); - controlreply(np, "Attempting to reload database. . ."); - } else { - controlreply(np, "An error occured after the database was unloaded, attempting reload. . ."); - } - if(trusts_loaddb()) { - controlreply(np, "Database reloaded successfully."); - } else { - controlreply(np, "An error occured, please reload the module manually."); - } + if(spaces + 5 >= sizeof(prebuf)) { + prebuf[0] = prebuf[1] = '\0'; } else { - controlreply(np, "Error %d occured during migration, commands reregistered.", errcode); - registercommands(0, NULL); + memset(prebuf, ' ', spaces); + prebuf[spaces] = '\0'; + } + + spacelen = width - (strlen(str) + spaces); + if(spacelen <= 0 || spacelen + 5 >= sizeof(postbuf)) { + postbuf[0] = postbuf[1] = '\0'; + } else { + memset(postbuf, ' ', spacelen); + postbuf[spacelen] = '\0'; } + + *_prebuf = prebuf; + *_postbuf = postbuf; } -static int trusts_cmdmigrate(void *source, int cargc, char **cargv) { - nick *sender = source; - int ret; +static void traverseandmark(unsigned int marker, trusthost *th, int markchildren) { + th->marker = marker; - /* iffy but temporary */ - ret = trusts_migration_start(migrate_status, (void *)(sender->numeric)); - if(!ret) { - controlreply(sender, "Migration started, commands deregistered."); - deregistercommands(0, NULL); - } else { - controlreply(sender, "Error %d starting migration.", ret); + if(markchildren) { + for(th=th->children;th;th=th->nextbychild) { + th->marker = marker; + traverseandmark(marker, th, markchildren); + } } +} - return CMD_OK; +static void insertth(array *parents, trusthost *th) { + int i; + trusthost **p2 = (trusthost **)(parents->content); + + /* this eliminates common subtrees */ + for(i=0;icursi;i++) + if(p2[i] == th) + break; + + if(i == parents->cursi) { + int pos = array_getfreeslot(parents); + ((trusthost **)(parents->content))[pos] = th; + } } -static trustgroup *tg_strtotg(char *name) { - unsigned long id; - trustgroup *tg; +static void marktree(array *parents, unsigned int marker, trusthost *th, int showchildren) { + trusthost *pth; + int parentcount = 0; - /* legacy format */ - if(name[0] == '#') { - id = strtoul(&name[1], NULL, 10); - if(id == ULONG_MAX) - return NULL; + for(pth=th->parent;pth;pth=pth->parent) { + insertth(parents, pth); - for(tg=tglist;tg;tg=tg->next) - if(tg->id == id) - return tg; + pth->marker = marker; } - for(tg=tglist;tg;tg=tg->next) - if(!match(name, tg->name->content)) - return tg; + if(parentcount == 0) + insertth(parents, th); + + /* sadly we need to recurse down */ + traverseandmark(marker, th, showchildren); +} + +static void outputtree(nick *np, unsigned int marker, trustgroup *originalgroup, trusthost *th, int depth, int showchildren) { + const char *cidrstr; + char *prespacebuf, *postspacebuf, parentbuf[512]; + + if(th->marker != marker) + return; + + cidrstr = CIDRtostr(th->ip, th->bits); + calculatespaces(depth + 2, 30 + 1, cidrstr, &prespacebuf, &postspacebuf); + + if(th->group == originalgroup) { + if(!showchildren && th->group == originalgroup && th->children) + prespacebuf[0] = '*'; + else + prespacebuf[0] = ' '; + + prespacebuf[1] = '>'; + + parentbuf[0] = '\0'; + } else { + /* show the ids of other groups */ + + snprintf(parentbuf, sizeof(parentbuf), "%-10d %s", th->group->id, th->group->name->content); + } - id = strtoul(name, NULL, 10); - if(id == ULONG_MAX) - return NULL; + controlreply(np, "%s%s%s %-10d %-10d %-21s %-15d /%-14d%s", prespacebuf, cidrstr, postspacebuf, th->count, th->maxusage, (th->count>0)?"(now)":((th->lastseen>0)?trusts_timetostr(th->lastseen):"(never)"), th->maxpernode, (irc_in_addr_is_ipv4(&th->ip))?(th->nodebits - 96):th->nodebits, parentbuf); - /* legacy format */ - for(tg=tglist;tg;tg=tg->next) - if(tg->id == id) - return tg; + /* Make sure we're not seeing this subtree again. */ + th->marker = -1; - return NULL; + for(th=th->children;th;th=th->nextbychild) + outputtree(np, marker, originalgroup, th, depth + 1, showchildren); } -static int trusts_cmdtrustlist(void *source, int cargc, char **cargv) { - nick *sender = source; - trustgroup *tg; - trusthost *th; - time_t t; +static char *formatflags(int flags) { + static char buf[512]; - if(cargc < 1) - return CMD_USAGE; + buf[0] = '\0'; - tg = tg_strtotg(cargv[0]); - if(!tg) { - controlreply(sender, "Couldn't find a trustgroup with that id."); - return CMD_ERROR; + if(flags & TRUST_ENFORCE_IDENT) + strncat(buf, "enforcing ident", 512); + + if(flags & TRUST_NO_CLEANUP) { + if(buf[0]) + strncat(buf, ", ", 512); + + strncat(buf, "exempt from cleanup", 512); } - t = time(NULL); + if(flags & TRUST_PROTECTED) { + if(buf[0]) + strncat(buf, ", ", 512); + strncat(buf, "protected", 512); + } + + if(flags & TRUST_RELIABLE_USERNAME) { + if(buf[0]) + strncat(buf, ", ", 512); + + strncat(buf, "reliable username", 512); + } + + if(flags & TRUST_UNTHROTTLE) { + if(buf[0]) + strncat(buf, ", ", 512); + + strncat(buf, "unthrottled", 512); + } + + buf[512-1] = '\0'; + + return buf; +} + +static char *formatlimit(unsigned int limit) { + static char buf[64]; + + if(limit) + snprintf(buf, sizeof(buf), "%u", limit); + else + strncpy(buf, "unlimited", sizeof(buf)); + + return buf; +} + +static void displaygroup(nick *sender, trustgroup *tg, int showchildren) { + trusthost *th, **p2; + unsigned int marker; + array parents; + int i; + time_t t = getnettime(); + + /* abusing the ternary operator a bit :( */ controlreply(sender, "Name: : %s", tg->name->content); - controlreply(sender, "Trusted for : %d", tg->trustedfor); + controlreply(sender, "Trusted for : %s", formatlimit(tg->trustedfor)); controlreply(sender, "Currently using : %d", tg->count); - controlreply(sender, "Clients per user : %d (%senforcing ident)", tg->maxperident, tg->mode?"":"not "); + controlreply(sender, "Clients per user : %s", formatlimit(tg->maxperident)); + controlreply(sender, "Flags : %s", formatflags(tg->flags)); controlreply(sender, "Contact: : %s", tg->contact->content); - controlreply(sender, "Expires in : %s", (tg->expires>t)?longtoduration(tg->expires - t, 2):"(in the past)"); - controlreply(sender, "Last changed by : %s", tg->createdby->content); + controlreply(sender, "Expires in : %s", (tg->expires)?((tg->expires>t)?longtoduration(tg->expires - t, 2):"the past (will be removed during next cleanup)"):"never"); + controlreply(sender, "Created by : %s", tg->createdby->content); controlreply(sender, "Comment: : %s", tg->comment->content); controlreply(sender, "ID: : %u", tg->id); - controlreply(sender, "Last used : %s", (tg->count>0)?"(now)":trusts_timetostr(tg->lastseen)); + controlreply(sender, "Last used : %s", (tg->count>0)?"(now)":((tg->lastseen>0)?trusts_timetostr(tg->lastseen):"(never)")); controlreply(sender, "Max usage : %d", tg->maxusage); - controlreply(sender, "Last max reset : %s", tg->lastmaxuserreset?trusts_timetostr(tg->lastmaxuserreset):"(never)"); + controlreply(sender, "Last max reset : %s", tg->lastmaxusereset?trusts_timetostr(tg->lastmaxusereset):"(never)"); + + controlreply(sender, "---"); + controlreply(sender, "Attributes: * (has hidden children, show with -v), > (belongs to this trust group)"); + controlreply(sender, "Host Current Max Last seen Max per Node Node Mask Group ID Group name"); - controlreply(sender, "Host Current Max Last seen"); + marker = nextthmarker(); + array_init(&parents, sizeof(trusthost *)); for(th=tg->hosts;th;th=th->next) - controlreply(sender, " %-20s %-10d %-10d %s", trusts_cidr2str(th->ip, th->mask), th->count, th->maxusage, (th->count>0)?"(now)":trusts_timetostr(th->lastseen)); + marktree(&parents, marker, th, showchildren); + + p2 = (trusthost **)(parents.content); + for(i=0;igroup, showchildren); + return CMD_OK; + } + + for(tg=tglist;tg;tg=tg->next) { + if(match(name, tg->name->content)) + continue; + + displaygroup(sender, tg, showchildren); + if(--remaining == 0) { + controlreply(sender, "Maximum number of matches reached."); + return CMD_OK; + } + found = 1; + } + + if(!found) + controlreply(sender, "No matches found."); return CMD_OK; } +static int trusts_cmdtrustglinesuggest(void *source, int cargc, char **cargv) { + nick *sender = source; + char mask[512]; + char *p, *user, *host; + struct irc_in_addr ip; + unsigned char bits; + int count; + glinebuf gbuf; + char creator[32]; + + if(cargc < 1) + return CMD_USAGE; + + strncpy(mask, cargv[0], sizeof(mask)); + + p = strchr(mask, '@'); + + if(!p) + return CMD_USAGE; + + user = mask; + host = p + 1; + *p = '\0'; + + if(!ipmask_parse(host, &ip, &bits)) { + controlreply(sender, "Invalid CIDR."); + return CMD_ERROR; + } + + snprintf(creator, sizeof(creator), "#%s", sender->authname); + + glinebufinit(&gbuf, 0); + glinebufaddbyip(&gbuf, user, &ip, 128, 0, creator, "Simulate", getnettime(), getnettime(), getnettime()); + glinebufcounthits(&gbuf, &count, NULL); + glinebufspew(&gbuf, sender); + glinebufabort(&gbuf); + + controlreply(sender, "Total hits: %d", count); + + return CMD_OK; +} + +static int trusts_cmdtrustspew(void *source, int cargc, char **cargv) { + nick *sender = source; + searchASTExpr tree; + + if(cargc < 1) + return CMD_USAGE; + + tree = NSASTNode(tgroup_parse, NSASTLiteral(cargv[0])); + return ast_nicksearch(&tree, controlreply, sender, NULL, printnick_channels, NULL, NULL, 2000); +} + static int commandsregistered; static void registercommands(int hooknum, void *arg) { @@ -126,8 +332,9 @@ static void registercommands(int hooknum, void *arg) { return; commandsregistered = 1; - registercontrolhelpcmd("trustmigrate", NO_DEVELOPER, 0, trusts_cmdmigrate, "Usage: trustmigrate\nCopies trust data from O and reloads the database."); - registercontrolhelpcmd("trustlist", NO_OPER, 1, trusts_cmdtrustlist, "Usage: trustlist <#id|name|id>\nShows trust data for the specified trust group."); + registercontrolhelpcmd("trustlist", NO_OPER, 2, trusts_cmdtrustlist, "Usage: trustlist [-v] <#id|name|IP>\nShows trust data for the specified trust group."); + registercontrolhelpcmd("trustglinesuggest", NO_OPER, 1, trusts_cmdtrustglinesuggest, "Usage: trustglinesuggest \nSuggests glines for the specified hostmask."); + registercontrolhelpcmd("trustspew", NO_OPER, 1, trusts_cmdtrustspew, "Usage: trustspew <#id|name>\nShows currently connected users for the specified trust group."); } static void deregistercommands(int hooknum, void *arg) { @@ -135,8 +342,9 @@ static void deregistercommands(int hooknum, void *arg) { return; commandsregistered = 0; - deregistercontrolcmd("trustmigrate", trusts_cmdmigrate); deregistercontrolcmd("trustlist", trusts_cmdtrustlist); + deregistercontrolcmd("trustglinesuggest", trusts_cmdtrustglinesuggest); + deregistercontrolcmd("trustspew", trusts_cmdtrustspew); } void _init(void) { @@ -151,7 +359,5 @@ void _fini(void) { deregisterhook(HOOK_TRUSTS_DB_LOADED, registercommands); deregisterhook(HOOK_TRUSTS_DB_CLOSED, deregistercommands); - trusts_migration_stop(); - deregistercommands(0, NULL); }