]> jfr.im git - irc/freenode/solanum.git/commitdiff
Keep propagated bans in a dictionary, not a list origin/edk/prop-ban-dictionary origin/prop-ban-dictionary
authorEd Kellett <redacted>
Wed, 3 Mar 2021 14:24:50 +0000 (14:24 +0000)
committerEd Kellett <redacted>
Sat, 10 Apr 2021 14:37:52 +0000 (15:37 +0100)
include/s_conf.h
ircd/s_conf.c
ircd/s_serv.c
modules/core/m_ban.c
modules/m_kline.c
modules/m_resv.c
modules/m_stats.c
modules/m_xline.c

index 8f7a1855fa815fe3bd8bf90c6019a859cb9fa4f6..0a388d31192292d8eb0753ae7e46cfe61a8dae06 100644 (file)
@@ -337,7 +337,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
 {
@@ -356,8 +356,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);
index c84047e452b7bd8848fdf44debfcbc647d2c6b33..284d94afbc772c09436b94153de681137d0f972c 100644 (file)
@@ -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);
@@ -1079,31 +1082,52 @@ 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)
 {
-       int i;
+       rb_dictionary_add(prop_bans_dict, aconf, aconf);
+}
 
-       s_assert(ptr->data == 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;
 
        switch (aconf->status)
        {
@@ -1145,7 +1169,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
@@ -1159,13 +1183,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;
@@ -1179,23 +1201,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)))
@@ -1211,7 +1231,7 @@ expire_prop_bans(void *list)
                                                     aconf->host ? aconf->host : "*");
 
                        /* will destroy or mark illegal */
-                       deactivate_conf(aconf, ptr, now);
+                       deactivate_conf(aconf, now);
                }
        }
 }
index 210ed8b1b029b1fc374a0d2aac2e8f6633b190d3..5dd25efa62713a481b7167111b82223878288849 100644 (file)
@@ -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;
index 897a40b02d2babbe469c4486983a2b17db26ece2..3ea11fd363100db106a096f63fe664c96f28aaa9 100644 (file)
@@ -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
index e478f50dc65ddf29387002d64de8224f9e72fc3b..2107deeb6289faf0d1fb32da7740f7f87f5341e3 100644 (file)
@@ -580,7 +580,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.. */
@@ -813,11 +813,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",
@@ -845,5 +843,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);
 }
index f0c14b4abff0cc09b75f2bf503cce61f089222a7..4160326cd53695bec887c9db17d625996b6d5951 100644 (file)
@@ -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)
index 49588aa1eb9d2872312b586208f4416e14a4a34d..d77791e52baf3b8ad1cfc08989071346fd795f16 100644 (file)
@@ -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,
index fb92bb9568e6439c49671244a98094350a3930a2..597f7618c244241873eccb7f0c6a46eb6838a5c9 100644 (file)
@@ -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))