X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/d914d1cbfd541d1c1302ac989a8c5b7d57d25f55..928e5a35af3dc82bdfbdd041dd3160e0a59aa01d:/src/shun.c diff --git a/src/shun.c b/src/shun.c index 1809764..950ad09 100644 --- a/src/shun.c +++ b/src/shun.c @@ -3,9 +3,9 @@ * * This file is part of x3. * - * srvx is free software; you can redistribute it and/or modify + * x3 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -40,6 +40,7 @@ #define KEY_REASON "reason" #define KEY_EXPIRES "expires" +#define KEY_LASTMOD "lastmod" #define KEY_ISSUER "issuer" #define KEY_ISSUED "issued" @@ -122,19 +123,13 @@ shun_remove(const char *target, int announce) timeq_add(new_first->expires, shun_expire, 0); } } -#ifdef WITH_PROTOCOL_BAHAMUT - /* Bahamut is sort of lame: It permanently remembers any AKILLs - * with durations longer than a day, and will never auto-expire - * them. So when the time comes, we'd better remind it. */ - announce = 1; -#endif if (announce) irc_unshun(target); return res; } struct shun * -shun_add(const char *issuer, const char *target, unsigned long duration, const char *reason, time_t issued, int announce) +shun_add(const char *issuer, const char *target, unsigned long duration, const char *reason, time_t issued, time_t lastmod, int announce) { struct shun *ent; struct shun *prev_first; @@ -147,9 +142,12 @@ shun_add(const char *issuer, const char *target, unsigned long duration, const c heap_remove_pred(shun_heap, shun_for_p, (char*)target); if (ent->expires < (time_t)(now + duration)) ent->expires = now + duration; + if (ent->lastmod < lastmod) + ent->lastmod = lastmod; } else { ent = malloc(sizeof(*ent)); ent->issued = issued; + ent->lastmod = lastmod; ent->issuer = strdup(issuer); ent->target = strdup(target); ent->expires = now + duration; @@ -170,8 +168,6 @@ static char * shun_alternate_target(const char *target) { const char *hostname; - unsigned long ip; - char *res; /* If no host part, bail. */ if (!(hostname = strchr(target, '@'))) @@ -179,23 +175,17 @@ shun_alternate_target(const char *target) /* If host part contains wildcards, bail. */ if (hostname[strcspn(hostname, "*?/")]) return NULL; - /* If host part looks like an IP, parse it that way. */ - if (!hostname[strspn(hostname+1, "0123456789.")+1]) { - struct in_addr in; - struct hostent *he; - if (inet_aton(hostname+1, &in) - && (he = gethostbyaddr((char*)&in, sizeof(in), AF_INET))) { - res = malloc((hostname - target) + 2 + strlen(he->h_name)); - sprintf(res, "%.*s@%s", hostname - target, target, he->h_name); - return res; - } else - return NULL; - } else if (getipbyname(hostname+1, &ip)) { - res = malloc((hostname - target) + 18); - sprintf(res, "%.*s@%lu.%lu.%lu.%lu", hostname - target, target, ip & 255, (ip >> 8) & 255, (ip >> 16) & 255, (ip >> 24) & 255); - return res; - } else - return NULL; + /* Get parsed address and canonical name for host. */ +#if 0 + irc_in_addr_t in; /* move this to the right place */ + if (irc_pton(&in, NULL, hostname+1)) { + if (getnameinfo(/*TODO*/)) + return NULL; + } else if (!getaddrinfo(/*TODO*/)) { + } else return NULL; +#else + return NULL; +#endif } struct shun * @@ -259,7 +249,7 @@ shun_add_record(const char *key, void *data, UNUSED_ARG(void *extra)) { struct record_data *rd = data; const char *issuer, *reason, *dstr; - time_t issued, expiration; + time_t issued, expiration, lastmod; if (!(reason = database_get_data(rd->d.object, KEY_REASON, RECDB_QSTRING))) { log_module(MAIN_LOG, LOG_ERROR, "Missing reason for shun %s", key); @@ -270,6 +260,8 @@ shun_add_record(const char *key, void *data, UNUSED_ARG(void *extra)) return 0; } expiration = strtoul(dstr, NULL, 0); + dstr = database_get_data(rd->d.object, KEY_LASTMOD, RECDB_QSTRING); + lastmod = dstr ? strtoul(dstr, NULL, 0) : 0; if ((dstr = database_get_data(rd->d.object, KEY_ISSUED, RECDB_QSTRING))) { issued = strtoul(dstr, NULL, 0); } else { @@ -279,7 +271,7 @@ shun_add_record(const char *key, void *data, UNUSED_ARG(void *extra)) issuer = ""; } if (expiration > now) - shun_add(issuer, key, expiration - now, reason, issued, 0); + shun_add(issuer, key, expiration - now, reason, issued, lastmod, 0); return 0; } @@ -298,6 +290,8 @@ shun_write_entry(UNUSED_ARG(void *key), void *data, void *extra) saxdb_start_record(ctx, ent->target, 0); saxdb_write_int(ctx, KEY_EXPIRES, ent->expires); saxdb_write_int(ctx, KEY_ISSUED, ent->issued); + if (ent->lastmod) + saxdb_write_int(ctx, KEY_LASTMOD, ent->lastmod); saxdb_write_string(ctx, KEY_REASON, ent->reason); saxdb_write_string(ctx, KEY_ISSUER, ent->issuer); saxdb_end_record(ctx); @@ -335,8 +329,9 @@ shun_discrim_create(struct userNode *user, struct userNode *src, unsigned int ar struct shun_discrim *discrim; discrim = calloc(1, sizeof(*discrim)); - discrim->max_issued = now; discrim->limit = 50; + discrim->max_issued = INT_MAX; + discrim->max_lastmod = INT_MAX; for (i=0; i argc) { @@ -371,7 +366,24 @@ shun_discrim_create(struct userNode *user, struct userNode *src, unsigned int ar discrim->min_expire = now + ParseInterval(argv[++i]); else if (!irccasecmp(argv[i], "before")) discrim->max_issued = now - ParseInterval(argv[++i]); - else { + else if (!irccasecmp(argv[i], "lastmod")) { + const char *cmp = argv[++i]; + if (cmp[0] == '<') { + if (cmp[1] == '=') { + discrim->min_lastmod = now - ParseInterval(cmp + 2); + } else { + discrim->min_lastmod = now - (ParseInterval(cmp + 1) - 1); + } + } else if (cmp[0] == '>') { + if (cmp[1] == '=') { + discrim->max_lastmod = now - ParseInterval(cmp + 2); + } else { + discrim->max_lastmod = now - (ParseInterval(cmp + 1) - 1); + } + } else { + discrim->min_lastmod = now - ParseInterval(cmp + 2); + } + } else { send_message(user, src, "MSG_INVALID_CRITERIA", argv[i]); goto fail; } @@ -409,7 +421,9 @@ shun_discrim_match(struct shun *shun, struct shun_discrim *discrim) && (!discrim->alt_target_mask || !match_ircglobs(discrim->alt_target_mask, shun->target))))) || (discrim->max_issued < shun->issued) - || (discrim->min_expire > shun->expires)) { + || (discrim->min_expire > shun->expires) + || (discrim->min_lastmod > shun->lastmod) + || (discrim->max_lastmod < shun->lastmod)) { return 0; } return 1;