Keep propagated bans in a dictionary, not a list

This commit is contained in:
Ed Kellett 2021-03-03 14:24:50 +00:00
parent 8b7110d6ba
commit ce376a21cc
8 changed files with 84 additions and 69 deletions

View file

@ -338,7 +338,7 @@ extern struct admin_info AdminInfo; /* defined in ircd.c */
extern rb_dlink_list service_list; extern rb_dlink_list service_list;
extern rb_dlink_list prop_bans; extern rb_dictionary *prop_bans_dict;
typedef enum temp_list typedef enum temp_list
{ {
@ -357,8 +357,11 @@ extern void init_s_conf(void);
extern struct ConfItem *make_conf(void); extern struct ConfItem *make_conf(void);
extern void free_conf(struct ConfItem *); extern void free_conf(struct ConfItem *);
extern rb_dlink_node *find_prop_ban(unsigned int status, const char *user, const char *host); extern struct ConfItem *find_prop_ban(unsigned int status, const char *user, const char *host);
extern void deactivate_conf(struct ConfItem *, rb_dlink_node *, time_t); 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 replace_old_ban(struct ConfItem *);
extern void read_conf_files(bool cold); extern void read_conf_files(bool cold);

View file

@ -62,22 +62,24 @@ extern char yy_linebuf[16384]; /* defined in ircd_lexer.l */
static rb_bh *confitem_heap = NULL; static rb_bh *confitem_heap = NULL;
rb_dlink_list prop_bans;
rb_dlink_list temp_klines[LAST_TEMP_TYPE]; rb_dlink_list temp_klines[LAST_TEMP_TYPE];
rb_dlink_list temp_dlines[LAST_TEMP_TYPE]; rb_dlink_list temp_dlines[LAST_TEMP_TYPE];
rb_dlink_list service_list; rb_dlink_list service_list;
rb_dictionary *prop_bans_dict;
/* internally defined functions */ /* internally defined functions */
static void set_default_conf(void); static void set_default_conf(void);
static void validate_conf(void); static void validate_conf(void);
static void read_conf(void); static void read_conf(void);
static void clear_out_old_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 expire_temp_kd(void *list);
static void reorganise_temp_kd(void *list); static void reorganise_temp_kd(void *list);
static int cmp_prop_ban(const void *, const void *);
FILE *conf_fbfile_in; FILE *conf_fbfile_in;
extern char yytext[]; extern char yytext[];
@ -89,8 +91,9 @@ void
init_s_conf(void) init_s_conf(void)
{ {
confitem_heap = rb_bh_create(sizeof(struct ConfItem), CONFITEM_HEAP_SIZE, "confitem_heap"); 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_klines", expire_temp_kd, &temp_klines[TEMP_MIN], 60);
rb_event_addish("expire_temp_dlines", expire_temp_kd, &temp_dlines[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; 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; const struct ConfItem *a = a_, *b = b_;
struct ConfItem *aconf; int r;
RB_DLINK_FOREACH(ptr, prop_bans.head) if ((a->status & ~CONF_ILLEGAL) > (int)(b->status & ~CONF_ILLEGAL)) return 1;
{ if ((a->status & ~CONF_ILLEGAL) < (int)(b->status & ~CONF_ILLEGAL)) return -1;
aconf = ptr->data;
if((aconf->status & ~CONF_ILLEGAL) == status && r = irccmp(a->host, b->host);
(!user || !aconf->user || if (r) return r;
!irccmp(aconf->user, user)) &&
!irccmp(aconf->host, host)) if (a->user && b->user)
return ptr; return irccmp(a->user, b->user);
}
return NULL; return 0;
} }
void 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; int i;
s_assert(ptr->data == aconf);
switch (aconf->status) switch (aconf->status)
{ {
case CONF_KILL: case CONF_KILL:
@ -1146,7 +1170,7 @@ deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr, time_t now)
else else
{ {
if (aconf->lifetime != 0) if (aconf->lifetime != 0)
rb_dlinkDestroy(ptr, &prop_bans); remove_prop_ban(aconf);
if (aconf->clients == 0) if (aconf->clients == 0)
free_conf(aconf); free_conf(aconf);
else else
@ -1160,13 +1184,11 @@ deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr, time_t now)
void void
replace_old_ban(struct ConfItem *aconf) replace_old_ban(struct ConfItem *aconf)
{ {
rb_dlink_node *ptr;
struct ConfItem *oldconf; struct ConfItem *oldconf;
ptr = find_prop_ban(aconf->status, aconf->user, aconf->host); oldconf = find_prop_ban(aconf->status, aconf->user, aconf->host);
if(ptr != NULL) if (oldconf != NULL)
{ {
oldconf = ptr->data;
/* Remember at least as long as the old one. */ /* Remember at least as long as the old one. */
if(oldconf->lifetime > aconf->lifetime) if(oldconf->lifetime > aconf->lifetime)
aconf->lifetime = oldconf->lifetime; aconf->lifetime = oldconf->lifetime;
@ -1180,23 +1202,21 @@ replace_old_ban(struct ConfItem *aconf)
aconf->lifetime = aconf->hold; aconf->lifetime = aconf->hold;
/* Tell deactivate_conf() to destroy it. */ /* Tell deactivate_conf() to destroy it. */
oldconf->lifetime = rb_current_time(); oldconf->lifetime = rb_current_time();
deactivate_conf(oldconf, ptr, oldconf->lifetime); deactivate_conf(oldconf, oldconf->lifetime);
} }
} }
static void static void
expire_prop_bans(void *list) expire_prop_bans(void *unused)
{ {
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
struct ConfItem *aconf; struct ConfItem *aconf;
time_t now; time_t now;
rb_dictionary_iter state;
now = rb_current_time(); 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 || if(aconf->lifetime <= now ||
(aconf->hold <= now && (aconf->hold <= now &&
!(aconf->status & CONF_ILLEGAL))) !(aconf->status & CONF_ILLEGAL)))
@ -1212,7 +1232,7 @@ expire_prop_bans(void *list)
aconf->host ? aconf->host : "*"); aconf->host ? aconf->host : "*");
/* will destroy or mark illegal */ /* will destroy or mark illegal */
deactivate_conf(aconf, ptr, now); deactivate_conf(aconf, now);
} }
} }
} }

View file

@ -472,14 +472,12 @@ send_capabilities(struct Client *client_p, unsigned int cap_can_send)
static void static void
burst_ban(struct Client *client_p) burst_ban(struct Client *client_p)
{ {
rb_dlink_node *ptr;
struct ConfItem *aconf; struct ConfItem *aconf;
const char *type; 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. */ /* Skip expired stuff. */
if(aconf->lifetime < rb_current_time()) if(aconf->lifetime < rb_current_time())
continue; continue;

View file

@ -82,7 +82,6 @@ m_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
static void static void
ms_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) 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; struct ConfItem *aconf;
unsigned int ntype; unsigned int ntype;
const char *oper, *stype; const char *oper, *stype;
@ -90,6 +89,7 @@ ms_ban(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
char *p; char *p;
int act; int act;
int valid; int valid;
bool new = false;
now = rb_current_time(); now = rb_current_time();
if (strlen(parv[1]) != 1) 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); oper = IsServer(source_p) ? source_p->name : get_oper_name(source_p);
else else
oper = parv[7]; oper = parv[7];
ptr = find_prop_ban(ntype, parv[2], parv[3]); aconf = find_prop_ban(ntype, parv[2], parv[3]);
if (ptr != NULL) if (aconf != NULL)
{ {
/* We already know about this ban mask. */ /* We already know about this ban mask. */
aconf = ptr->data;
if (aconf->created > created || if (aconf->created > created ||
(aconf->created == created && (aconf->created == created &&
aconf->lifetime >= lifetime)) 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) if (aconf->lifetime <= now)
return; return;
/* Deactivate, it will be reactivated later if appropriate. */ /* Deactivate, it will be reactivated later if appropriate. */
deactivate_conf(aconf, ptr, now); deactivate_conf(aconf, now);
rb_free(aconf->user); rb_free(aconf->user);
aconf->user = NULL; aconf->user = NULL;
rb_free(aconf->host); 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 = make_conf();
aconf->status = CONF_ILLEGAL | ntype; aconf->status = CONF_ILLEGAL | ntype;
aconf->lifetime = lifetime; aconf->lifetime = lifetime;
rb_dlinkAddAlloc(aconf, &prop_bans);
act = hold != created && hold > now; act = hold != created && hold > now;
new = true;
} }
aconf->flags &= ~CONF_FLAGS_MYOPER; aconf->flags &= ~CONF_FLAGS_MYOPER;
aconf->flags |= CONF_FLAGS_TEMPORARY; 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->info.oper = operhash_add(oper);
aconf->created = created; aconf->created = created;
aconf->hold = hold; aconf->hold = hold;
if (new)
add_prop_ban(aconf);
if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL) if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL)
aconf->passwd = rb_strdup(parv[parc - 1]); aconf->passwd = rb_strdup(parv[parc - 1]);
else else

View file

@ -602,7 +602,7 @@ apply_prop_kline(struct Client *source_p, struct ConfItem *aconf,
replace_old_ban(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); add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
/* no oper reason.. */ /* no oper reason.. */
@ -860,11 +860,9 @@ remove_temp_kline(struct Client *source_p, struct ConfItem *aconf)
static void static void
remove_prop_kline(struct Client *source_p, struct ConfItem *aconf) remove_prop_kline(struct Client *source_p, struct ConfItem *aconf)
{ {
rb_dlink_node *ptr;
time_t now; time_t now;
ptr = rb_dlinkFind(aconf, &prop_bans); if (!lookup_prop_ban(aconf))
if (!ptr)
return; return;
sendto_one_notice(source_p, sendto_one_notice(source_p,
":Un-klined [%s@%s] from global k-lines", ":Un-klined [%s@%s] from global k-lines",
@ -892,5 +890,5 @@ remove_prop_kline(struct Client *source_p, struct ConfItem *aconf)
0, 0,
(int)(aconf->lifetime - aconf->created)); (int)(aconf->lifetime - aconf->created));
remove_reject_mask(aconf->user, aconf->host); remove_reject_mask(aconf->user, aconf->host);
deactivate_conf(aconf, ptr, now); deactivate_conf(aconf, now);
} }

View 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->hold = rb_current_time() + temp_time;
aconf->lifetime = aconf->hold; aconf->lifetime = aconf->hold;
replace_old_ban(aconf); replace_old_ban(aconf);
rb_dlinkAddAlloc(aconf, &prop_bans); add_prop_ban(aconf);
sendto_realops_snomask(SNO_GENERAL, L_ALL, sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s added global %d min. RESV for [%s] [%s]", "%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->hold = rb_current_time() + temp_time;
aconf->lifetime = aconf->hold; aconf->lifetime = aconf->hold;
replace_old_ban(aconf); replace_old_ban(aconf);
rb_dlinkAddAlloc(aconf, &prop_bans); add_prop_ban(aconf);
sendto_realops_snomask(SNO_GENERAL, L_ALL, sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s added global %d min. RESV for [%s] [%s]", "%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); sendto_one_notice(source_p, ":Cannot remove global RESV %s on specific servers", name);
return; return;
} }
ptr = rb_dlinkFind(aconf, &prop_bans); if (!lookup_prop_ban(aconf))
if(ptr == NULL)
return; return;
sendto_one_notice(source_p, ":RESV for [%s] is removed", name); sendto_one_notice(source_p, ":RESV for [%s] is removed", name);
sendto_realops_snomask(SNO_GENERAL, L_ALL, 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, (unsigned long)aconf->created,
0, 0,
(int)(aconf->lifetime - aconf->created)); (int)(aconf->lifetime - aconf->created));
deactivate_conf(aconf, ptr, now); deactivate_conf(aconf, now);
return; return;
} }
else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0) 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); sendto_one_notice(source_p, ":Cannot remove global RESV %s on specific servers", name);
return; return;
} }
ptr = rb_dlinkFind(aconf, &prop_bans); if (!lookup_prop_ban(aconf))
if(ptr == NULL)
return; return;
sendto_one_notice(source_p, ":RESV for [%s] is removed", name); sendto_one_notice(source_p, ":RESV for [%s] is removed", name);
sendto_realops_snomask(SNO_GENERAL, L_ALL, 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, (unsigned long)aconf->created,
0, 0,
(int)(aconf->lifetime - aconf->created)); (int)(aconf->lifetime - aconf->created));
deactivate_conf(aconf, ptr, now); deactivate_conf(aconf, now);
return; return;
} }
else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0) else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0)

View file

@ -503,15 +503,13 @@ static void
stats_prop_klines(struct Client *source_p) stats_prop_klines(struct Client *source_p)
{ {
struct ConfItem *aconf; struct ConfItem *aconf;
rb_dlink_node *ptr;
char *user, *host, *pass, *oper_reason; 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. */ /* Skip non-klines and deactivated klines. */
if(aconf->status != CONF_KILL) if (aconf->status != CONF_KILL)
continue; continue;
get_printable_kline(source_p, aconf, &host, &pass, get_printable_kline(source_p, aconf, &host, &pass,

View file

@ -285,7 +285,7 @@ apply_xline(struct Client *source_p, const char *name, const char *reason, int t
aconf->lifetime = aconf->hold; aconf->lifetime = aconf->hold;
replace_old_ban(aconf); replace_old_ban(aconf);
rb_dlinkAddAlloc(aconf, &prop_bans); add_prop_ban(aconf);
sendto_realops_snomask(SNO_GENERAL, L_ALL, sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s added global %d min. X-Line for [%s] [%s]", "%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); sendto_one_notice(source_p, ":Cannot remove global X-Line %s on specific servers", name);
return; return;
} }
ptr = rb_dlinkFind(aconf, &prop_bans); if (!lookup_prop_ban(aconf))
if(ptr == NULL)
return; return;
sendto_one_notice(source_p, ":X-Line for [%s] is removed", name); sendto_one_notice(source_p, ":X-Line for [%s] is removed", name);
sendto_realops_snomask(SNO_GENERAL, L_ALL, sendto_realops_snomask(SNO_GENERAL, L_ALL,
@ -499,7 +498,7 @@ remove_xline(struct Client *source_p, const char *name, bool propagated)
0, 0,
(int)(aconf->lifetime - aconf->created)); (int)(aconf->lifetime - aconf->created));
remove_reject_mask(aconf->host, NULL); remove_reject_mask(aconf->host, NULL);
deactivate_conf(aconf, ptr, now); deactivate_conf(aconf, now);
return; return;
} }
else if(propagated && rb_dlink_list_length(&cluster_conf_list)) else if(propagated && rb_dlink_list_length(&cluster_conf_list))