From ce376a21ccc6ffa404e8b77b18e6db4c1d336f0a Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Wed, 3 Mar 2021 14:24:50 +0000 Subject: [PATCH] Keep propagated bans in a dictionary, not a list --- include/s_conf.h | 9 +++-- ircd/s_conf.c | 88 +++++++++++++++++++++++++++----------------- ircd/s_serv.c | 6 +-- modules/core/m_ban.c | 13 ++++--- modules/m_kline.c | 8 ++-- modules/m_resv.c | 14 +++---- modules/m_stats.c | 8 ++-- modules/m_xline.c | 7 ++-- 8 files changed, 84 insertions(+), 69 deletions(-) diff --git a/include/s_conf.h b/include/s_conf.h index ae1ef15e..ce5d9388 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -338,7 +338,7 @@ extern struct admin_info AdminInfo; /* defined in ircd.c */ extern rb_dlink_list service_list; -extern rb_dlink_list prop_bans; +extern rb_dictionary *prop_bans_dict; typedef enum temp_list { @@ -357,8 +357,11 @@ extern void init_s_conf(void); extern struct ConfItem *make_conf(void); extern void free_conf(struct ConfItem *); -extern rb_dlink_node *find_prop_ban(unsigned int status, const char *user, const char *host); -extern void deactivate_conf(struct ConfItem *, rb_dlink_node *, time_t); +extern struct ConfItem *find_prop_ban(unsigned int status, const char *user, const char *host); +extern void add_prop_ban(struct ConfItem *); +extern void remove_prop_ban(struct ConfItem *); +extern bool lookup_prop_ban(struct ConfItem *); +extern void deactivate_conf(struct ConfItem *, time_t); extern void replace_old_ban(struct ConfItem *); extern void read_conf_files(bool cold); diff --git a/ircd/s_conf.c b/ircd/s_conf.c index a35d64a8..28cf6647 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -62,22 +62,24 @@ extern char yy_linebuf[16384]; /* defined in ircd_lexer.l */ static rb_bh *confitem_heap = NULL; -rb_dlink_list prop_bans; - rb_dlink_list temp_klines[LAST_TEMP_TYPE]; rb_dlink_list temp_dlines[LAST_TEMP_TYPE]; rb_dlink_list service_list; +rb_dictionary *prop_bans_dict; + /* internally defined functions */ static void set_default_conf(void); static void validate_conf(void); static void read_conf(void); static void clear_out_old_conf(void); -static void expire_prop_bans(void *list); +static void expire_prop_bans(void *); static void expire_temp_kd(void *list); static void reorganise_temp_kd(void *list); +static int cmp_prop_ban(const void *, const void *); + FILE *conf_fbfile_in; extern char yytext[]; @@ -89,8 +91,9 @@ void init_s_conf(void) { confitem_heap = rb_bh_create(sizeof(struct ConfItem), CONFITEM_HEAP_SIZE, "confitem_heap"); + prop_bans_dict = rb_dictionary_create("prop_bans", cmp_prop_ban); - rb_event_addish("expire_prop_bans", expire_prop_bans, &prop_bans, 60); + rb_event_addish("expire_prop_bans", expire_prop_bans, NULL, 60); rb_event_addish("expire_temp_klines", expire_temp_kd, &temp_klines[TEMP_MIN], 60); rb_event_addish("expire_temp_dlines", expire_temp_kd, &temp_dlines[TEMP_MIN], 60); @@ -1080,32 +1083,53 @@ valid_wild_card(const char *luser, const char *lhost) return 0; } -rb_dlink_node * -find_prop_ban(unsigned int status, const char *user, const char *host) + +int cmp_prop_ban(const void *a_, const void *b_) { - rb_dlink_node *ptr; - struct ConfItem *aconf; + const struct ConfItem *a = a_, *b = b_; + int r; - RB_DLINK_FOREACH(ptr, prop_bans.head) - { - aconf = ptr->data; + if ((a->status & ~CONF_ILLEGAL) > (int)(b->status & ~CONF_ILLEGAL)) return 1; + if ((a->status & ~CONF_ILLEGAL) < (int)(b->status & ~CONF_ILLEGAL)) return -1; - if((aconf->status & ~CONF_ILLEGAL) == status && - (!user || !aconf->user || - !irccmp(aconf->user, user)) && - !irccmp(aconf->host, host)) - return ptr; - } - return NULL; + r = irccmp(a->host, b->host); + if (r) return r; + + if (a->user && b->user) + return irccmp(a->user, b->user); + + return 0; } void -deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr, time_t now) +add_prop_ban(struct ConfItem *aconf) +{ + rb_dictionary_add(prop_bans_dict, aconf, aconf); +} + +struct ConfItem * +find_prop_ban(unsigned status, const char *user, const char *host) +{ + struct ConfItem key = {.status = status, .user = (char *)user, .host = (char *)host}; + return rb_dictionary_retrieve(prop_bans_dict, &key); +} + +void +remove_prop_ban(struct ConfItem *aconf) +{ + rb_dictionary_delete(prop_bans_dict, aconf); +} + +bool lookup_prop_ban(struct ConfItem *aconf) +{ + return rb_dictionary_retrieve(prop_bans_dict, aconf) == aconf; +} + +void +deactivate_conf(struct ConfItem *aconf, time_t now) { int i; - s_assert(ptr->data == aconf); - switch (aconf->status) { case CONF_KILL: @@ -1146,7 +1170,7 @@ deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr, time_t now) else { if (aconf->lifetime != 0) - rb_dlinkDestroy(ptr, &prop_bans); + remove_prop_ban(aconf); if (aconf->clients == 0) free_conf(aconf); else @@ -1160,13 +1184,11 @@ deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr, time_t now) void replace_old_ban(struct ConfItem *aconf) { - rb_dlink_node *ptr; struct ConfItem *oldconf; - ptr = find_prop_ban(aconf->status, aconf->user, aconf->host); - if(ptr != NULL) + oldconf = find_prop_ban(aconf->status, aconf->user, aconf->host); + if (oldconf != NULL) { - oldconf = ptr->data; /* Remember at least as long as the old one. */ if(oldconf->lifetime > aconf->lifetime) aconf->lifetime = oldconf->lifetime; @@ -1180,23 +1202,21 @@ replace_old_ban(struct ConfItem *aconf) aconf->lifetime = aconf->hold; /* Tell deactivate_conf() to destroy it. */ oldconf->lifetime = rb_current_time(); - deactivate_conf(oldconf, ptr, oldconf->lifetime); + deactivate_conf(oldconf, oldconf->lifetime); } } static void -expire_prop_bans(void *list) +expire_prop_bans(void *unused) { - rb_dlink_node *ptr; - rb_dlink_node *next_ptr; struct ConfItem *aconf; time_t now; + rb_dictionary_iter state; now = rb_current_time(); - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, ((rb_dlink_list *) list)->head) - { - aconf = ptr->data; + RB_DICTIONARY_FOREACH(aconf, &state, prop_bans_dict) + { if(aconf->lifetime <= now || (aconf->hold <= now && !(aconf->status & CONF_ILLEGAL))) @@ -1212,7 +1232,7 @@ expire_prop_bans(void *list) aconf->host ? aconf->host : "*"); /* will destroy or mark illegal */ - deactivate_conf(aconf, ptr, now); + deactivate_conf(aconf, now); } } } diff --git a/ircd/s_serv.c b/ircd/s_serv.c index 7ce1daf2..23720889 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -472,14 +472,12 @@ send_capabilities(struct Client *client_p, unsigned int cap_can_send) static void burst_ban(struct Client *client_p) { - rb_dlink_node *ptr; struct ConfItem *aconf; const char *type; + rb_dictionary_iter state; - RB_DLINK_FOREACH(ptr, prop_bans.head) + RB_DICTIONARY_FOREACH(aconf, &state, prop_bans_dict) { - aconf = ptr->data; - /* Skip expired stuff. */ if(aconf->lifetime < rb_current_time()) continue; diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index 897a40b0..3ea11fd3 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -82,7 +82,6 @@ m_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, static void ms_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { - rb_dlink_node *ptr; struct ConfItem *aconf; unsigned int ntype; const char *oper, *stype; @@ -90,6 +89,7 @@ ms_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p char *p; int act; int valid; + bool new = false; now = rb_current_time(); if (strlen(parv[1]) != 1) @@ -127,11 +127,10 @@ ms_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p oper = IsServer(source_p) ? source_p->name : get_oper_name(source_p); else oper = parv[7]; - ptr = find_prop_ban(ntype, parv[2], parv[3]); - if (ptr != NULL) + aconf = find_prop_ban(ntype, parv[2], parv[3]); + if (aconf != NULL) { /* We already know about this ban mask. */ - aconf = ptr->data; if (aconf->created > created || (aconf->created == created && aconf->lifetime >= lifetime)) @@ -158,7 +157,7 @@ ms_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p if (aconf->lifetime <= now) return; /* Deactivate, it will be reactivated later if appropriate. */ - deactivate_conf(aconf, ptr, now); + deactivate_conf(aconf, now); rb_free(aconf->user); aconf->user = NULL; rb_free(aconf->host); @@ -176,8 +175,8 @@ ms_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p aconf = make_conf(); aconf->status = CONF_ILLEGAL | ntype; aconf->lifetime = lifetime; - rb_dlinkAddAlloc(aconf, &prop_bans); act = hold != created && hold > now; + new = true; } aconf->flags &= ~CONF_FLAGS_MYOPER; aconf->flags |= CONF_FLAGS_TEMPORARY; @@ -186,6 +185,8 @@ ms_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p aconf->info.oper = operhash_add(oper); aconf->created = created; aconf->hold = hold; + if (new) + add_prop_ban(aconf); if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL) aconf->passwd = rb_strdup(parv[parc - 1]); else diff --git a/modules/m_kline.c b/modules/m_kline.c index b4d8c3f4..2a3fc99d 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -602,7 +602,7 @@ apply_prop_kline(struct Client *source_p, struct ConfItem *aconf, replace_old_ban(aconf); - rb_dlinkAddAlloc(aconf, &prop_bans); + add_prop_ban(aconf); add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf); /* no oper reason.. */ @@ -860,11 +860,9 @@ remove_temp_kline(struct Client *source_p, struct ConfItem *aconf) static void remove_prop_kline(struct Client *source_p, struct ConfItem *aconf) { - rb_dlink_node *ptr; time_t now; - ptr = rb_dlinkFind(aconf, &prop_bans); - if (!ptr) + if (!lookup_prop_ban(aconf)) return; sendto_one_notice(source_p, ":Un-klined [%s@%s] from global k-lines", @@ -892,5 +890,5 @@ remove_prop_kline(struct Client *source_p, struct ConfItem *aconf) 0, (int)(aconf->lifetime - aconf->created)); remove_reject_mask(aconf->user, aconf->host); - deactivate_conf(aconf, ptr, now); + deactivate_conf(aconf, now); } diff --git a/modules/m_resv.c b/modules/m_resv.c index f0c14b4a..4160326c 100644 --- a/modules/m_resv.c +++ b/modules/m_resv.c @@ -228,7 +228,7 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf->hold = rb_current_time() + temp_time; aconf->lifetime = aconf->hold; replace_old_ban(aconf); - rb_dlinkAddAlloc(aconf, &prop_bans); + add_prop_ban(aconf); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s added global %d min. RESV for [%s] [%s]", @@ -312,7 +312,7 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf->hold = rb_current_time() + temp_time; aconf->lifetime = aconf->hold; replace_old_ban(aconf); - rb_dlinkAddAlloc(aconf, &prop_bans); + add_prop_ban(aconf); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s added global %d min. RESV for [%s] [%s]", @@ -511,8 +511,7 @@ remove_resv(struct Client *source_p, const char *name, int propagated) sendto_one_notice(source_p, ":Cannot remove global RESV %s on specific servers", name); return; } - ptr = rb_dlinkFind(aconf, &prop_bans); - if(ptr == NULL) + if (!lookup_prop_ban(aconf)) return; sendto_one_notice(source_p, ":RESV for [%s] is removed", name); sendto_realops_snomask(SNO_GENERAL, L_ALL, @@ -534,7 +533,7 @@ remove_resv(struct Client *source_p, const char *name, int propagated) (unsigned long)aconf->created, 0, (int)(aconf->lifetime - aconf->created)); - deactivate_conf(aconf, ptr, now); + deactivate_conf(aconf, now); return; } else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0) @@ -585,8 +584,7 @@ remove_resv(struct Client *source_p, const char *name, int propagated) sendto_one_notice(source_p, ":Cannot remove global RESV %s on specific servers", name); return; } - ptr = rb_dlinkFind(aconf, &prop_bans); - if(ptr == NULL) + if (!lookup_prop_ban(aconf)) return; sendto_one_notice(source_p, ":RESV for [%s] is removed", name); sendto_realops_snomask(SNO_GENERAL, L_ALL, @@ -608,7 +606,7 @@ remove_resv(struct Client *source_p, const char *name, int propagated) (unsigned long)aconf->created, 0, (int)(aconf->lifetime - aconf->created)); - deactivate_conf(aconf, ptr, now); + deactivate_conf(aconf, now); return; } else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0) diff --git a/modules/m_stats.c b/modules/m_stats.c index 49588aa1..d77791e5 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -503,15 +503,13 @@ static void stats_prop_klines(struct Client *source_p) { struct ConfItem *aconf; - rb_dlink_node *ptr; char *user, *host, *pass, *oper_reason; + rb_dictionary_iter state; - RB_DLINK_FOREACH(ptr, prop_bans.head) + RB_DICTIONARY_FOREACH(aconf, &state, prop_bans_dict) { - aconf = ptr->data; - /* Skip non-klines and deactivated klines. */ - if(aconf->status != CONF_KILL) + if (aconf->status != CONF_KILL) continue; get_printable_kline(source_p, aconf, &host, &pass, diff --git a/modules/m_xline.c b/modules/m_xline.c index fb92bb95..597f7618 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -285,7 +285,7 @@ apply_xline(struct Client *source_p, const char *name, const char *reason, int t aconf->lifetime = aconf->hold; replace_old_ban(aconf); - rb_dlinkAddAlloc(aconf, &prop_bans); + add_prop_ban(aconf); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s added global %d min. X-Line for [%s] [%s]", @@ -475,8 +475,7 @@ remove_xline(struct Client *source_p, const char *name, bool propagated) sendto_one_notice(source_p, ":Cannot remove global X-Line %s on specific servers", name); return; } - ptr = rb_dlinkFind(aconf, &prop_bans); - if(ptr == NULL) + if (!lookup_prop_ban(aconf)) return; sendto_one_notice(source_p, ":X-Line for [%s] is removed", name); sendto_realops_snomask(SNO_GENERAL, L_ALL, @@ -499,7 +498,7 @@ remove_xline(struct Client *source_p, const char *name, bool propagated) 0, (int)(aconf->lifetime - aconf->created)); remove_reject_mask(aconf->host, NULL); - deactivate_conf(aconf, ptr, now); + deactivate_conf(aconf, now); return; } else if(propagated && rb_dlink_list_length(&cluster_conf_list))