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 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);

View 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);
@ -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);
}
}
}

View 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;

View 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

View file

@ -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);
}

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->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)

View 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,

View 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))