X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fgline.c;h=bb169ab1cadca42875d0f6c5ddf54186c0832cb0;hb=80d9ed728be4b02ac483f3339cbb184f6602d15b;hp=318791991f63afd686ed8fa2d6d155957e9aeb91;hpb=bfe215c2fe8eb715e4e7b929aa13d87066143776;p=srvx.git diff --git a/src/gline.c b/src/gline.c index 3187919..bb169ab 100644 --- a/src/gline.c +++ b/src/gline.c @@ -40,8 +40,10 @@ #define KEY_REASON "reason" #define KEY_EXPIRES "expires" +#define KEY_LASTMOD "lastmod" #define KEY_ISSUER "issuer" #define KEY_ISSUED "issued" +#define KEY_LIFETIME "lifetime" static heap_t gline_heap; /* key: expiry time, data: struct gline_entry* */ static dict_t gline_dict; /* key: target, data: struct gline_entry* */ @@ -50,7 +52,7 @@ static int gline_comparator(const void *a, const void *b) { const struct gline *ga=a, *gb=b; - return ga->expires - gb->expires; + return ga->lifetime - gb->lifetime; } static void @@ -70,35 +72,21 @@ free_gline(struct gline *ent) } static int -gline_for_p(UNUSED_ARG(void *key), void *data, void *extra) +gline_equal_p(UNUSED_ARG(void *key), void *data, void *extra) { - struct gline *ge = data; - return !irccasecmp(ge->target, extra); -} - -static int -delete_gline_for_p(UNUSED_ARG(void *key), void *data, void *extra) -{ - struct gline *ge = data; - - if (!irccasecmp(ge->target, extra)) { - free_gline(ge); - return 1; - } else { - return 0; - } + return data == extra; } static void gline_expire(UNUSED_ARG(void *data)) { - time_t stopped; + unsigned long stopped; void *wraa; stopped = 0; while (heap_size(gline_heap)) { heap_peek(gline_heap, 0, &wraa); - stopped = ((struct gline*)wraa)->expires; + stopped = ((struct gline*)wraa)->lifetime; if (stopped > now) break; heap_pop(gline_heap); @@ -111,55 +99,59 @@ gline_expire(UNUSED_ARG(void *data)) int gline_remove(const char *target, int announce) { - int res = dict_find(gline_dict, target, NULL) ? 1 : 0; - if (heap_remove_pred(gline_heap, delete_gline_for_p, (char*)target)) { - void *argh; - struct gline *new_first; - heap_peek(gline_heap, 0, &argh); - if (argh) { - new_first = argh; - timeq_del(0, gline_expire, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA); - timeq_add(new_first->expires, gline_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 + struct gline *gl; + + gl = dict_find(gline_dict, target, NULL); + if (gl != NULL) + gl->expires = now; if (announce) irc_ungline(target); - return res; + return gl != NULL; } struct gline * -gline_add(const char *issuer, const char *target, unsigned long duration, const char *reason, time_t issued, int announce) +gline_add(const char *issuer, const char *target, unsigned long duration, const char *reason, unsigned long issued, unsigned long lastmod, unsigned long lifetime, int announce) { struct gline *ent; struct gline *prev_first; void *argh; + unsigned long expires; heap_peek(gline_heap, 0, &argh); prev_first = argh; + expires = now + duration; + if (lifetime < expires) + lifetime = expires; ent = dict_find(gline_dict, target, NULL); if (ent) { - heap_remove_pred(gline_heap, gline_for_p, (char*)target); - if (ent->expires < (time_t)(now + duration)) - ent->expires = now + duration; + heap_remove_pred(gline_heap, gline_equal_p, ent); + if (ent->issued > lastmod) + ent->issued = lastmod; + if (ent->lastmod < lastmod) { + ent->lastmod = lastmod; + ent->expires = expires; + if (strcmp(ent->reason, reason)) { + free(ent->reason); + ent->reason = strdup(reason); + } + } + if (ent->lifetime < lifetime) + ent->lifetime = lifetime; } else { ent = malloc(sizeof(*ent)); ent->issued = issued; + ent->lastmod = lastmod; ent->issuer = strdup(issuer); ent->target = strdup(target); - ent->expires = now + duration; + ent->expires = expires; + ent->lifetime = lifetime; ent->reason = strdup(reason); dict_insert(gline_dict, ent->target, ent); } heap_insert(gline_heap, ent, ent); - if (!prev_first || (ent->expires < prev_first->expires)) { - timeq_del(0, gline_expire, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA); - timeq_add(ent->expires, gline_expire, 0); + if (!prev_first || (ent->lifetime < prev_first->lifetime)) { + timeq_del(0, gline_expire, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA); + timeq_add(ent->lifetime, gline_expire, 0); } if (announce) irc_gline(NULL, ent); @@ -170,8 +162,6 @@ static char * gline_alternate_target(const char *target) { const char *hostname; - unsigned long ip; - char *res; /* If no host part, bail. */ if (!(hostname = strchr(target, '@'))) @@ -179,23 +169,17 @@ gline_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(&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 gline * @@ -259,27 +243,27 @@ gline_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; + unsigned long issued, expiration, lastmod, lifetime; if (!(reason = database_get_data(rd->d.object, KEY_REASON, RECDB_QSTRING))) { - log_module(MAIN_LOG, LOG_ERROR, "Missing reason for gline %s", key); - return 0; + log_module(MAIN_LOG, LOG_ERROR, "Missing reason for gline %s", key); + return 0; } if (!(dstr = database_get_data(rd->d.object, KEY_EXPIRES, RECDB_QSTRING))) { - log_module(MAIN_LOG, LOG_ERROR, "Missing expiration for gline %s", key); - return 0; + log_module(MAIN_LOG, LOG_ERROR, "Missing expiration for gline %s", key); + return 0; } expiration = strtoul(dstr, NULL, 0); - if ((dstr = database_get_data(rd->d.object, KEY_ISSUED, RECDB_QSTRING))) { - issued = strtoul(dstr, NULL, 0); - } else { - issued = now; - } - if (!(issuer = database_get_data(rd->d.object, KEY_ISSUER, RECDB_QSTRING))) { + dstr = database_get_data(rd->d.object, KEY_LIFETIME, RECDB_QSTRING); + lifetime = dstr ? strtoul(dstr, NULL, 0) : expiration; + dstr = database_get_data(rd->d.object, KEY_LASTMOD, RECDB_QSTRING); + lastmod = dstr ? strtoul(dstr, NULL, 0) : 0; + dstr = database_get_data(rd->d.object, KEY_ISSUED, RECDB_QSTRING); + issued = dstr ? strtoul(dstr, NULL, 0) : now; + if (!(issuer = database_get_data(rd->d.object, KEY_ISSUER, RECDB_QSTRING))) issuer = ""; - } - if (expiration > now) - gline_add(issuer, key, expiration - now, reason, issued, 0); + if (lifetime > now) + gline_add(issuer, key, expiration - now, reason, issued, lastmod, lifetime, 0); return 0; } @@ -298,6 +282,9 @@ gline_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); + saxdb_write_int(ctx, KEY_LIFETIME, ent->lifetime); + 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 +322,10 @@ gline_discrim_create(struct userNode *user, struct userNode *src, unsigned int a struct gline_discrim *discrim; discrim = calloc(1, sizeof(*discrim)); - discrim->max_issued = now; discrim->limit = 50; + discrim->max_issued = ULONG_MAX; + discrim->max_lastmod = ULONG_MAX; + discrim->max_lifetime = ULONG_MAX; for (i=0; i argc) { @@ -371,7 +360,41 @@ gline_discrim_create(struct userNode *user, struct userNode *src, unsigned int a 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 if (!irccasecmp(argv[i], "lifetime")) { + const char *cmp = argv[++i]; + if (cmp[0] == '<') { + if (cmp[1] == '=') { + discrim->min_lifetime = now - ParseInterval(cmp + 2); + } else { + discrim->min_lifetime = now - (ParseInterval(cmp + 1) - 1); + } + } else if (cmp[0] == '>') { + if (cmp[1] == '=') { + discrim->max_lifetime = now - ParseInterval(cmp + 2); + } else { + discrim->max_lifetime = now - (ParseInterval(cmp + 1) - 1); + } + } else { + discrim->min_lifetime = now - ParseInterval(cmp + 2); + } + } else { send_message(user, src, "MSG_INVALID_CRITERIA", argv[i]); goto fail; } @@ -409,7 +432,11 @@ gline_discrim_match(struct gline *gline, struct gline_discrim *discrim) && (!discrim->alt_target_mask || !match_ircglobs(discrim->alt_target_mask, gline->target))))) || (discrim->max_issued < gline->issued) - || (discrim->min_expire > gline->expires)) { + || (discrim->min_expire > gline->expires) + || (discrim->min_lastmod > gline->lastmod) + || (discrim->max_lastmod < gline->lastmod) + || (discrim->min_lifetime > gline->lifetime) + || (discrim->max_lifetime < gline->lifetime)) { return 0; } return 1;