Allow temporary K-lines to extend shorter ones (#142)
* Temp K-lines may extend shorter temp K-lines * /unkline removes multiple matching K-lines * K-lines remove any temp K-lines they're replacing
This commit is contained in:
parent
788e1a98f0
commit
3ff5a12e75
3 changed files with 100 additions and 42 deletions
|
@ -46,6 +46,8 @@ struct ConfItem *find_conf_by_address(const char *host, const char *sockhost,
|
||||||
int, int, const char *, const char *);
|
int, int, const char *, const char *);
|
||||||
struct ConfItem *find_exact_conf_by_address(const char *address, int type,
|
struct ConfItem *find_exact_conf_by_address(const char *address, int type,
|
||||||
const char *username);
|
const char *username);
|
||||||
|
struct ConfItem *find_exact_conf_by_address_filtered(const char *address, int type,
|
||||||
|
const char *username, bool (*filter)(struct ConfItem *));
|
||||||
void add_conf_by_address(const char *, int, const char *, const char *, struct ConfItem *);
|
void add_conf_by_address(const char *, int, const char *, const char *, struct ConfItem *);
|
||||||
void delete_one_address_conf(const char *, struct ConfItem *);
|
void delete_one_address_conf(const char *, struct ConfItem *);
|
||||||
void clear_out_address_conf(enum aconf_category);
|
void clear_out_address_conf(enum aconf_category);
|
||||||
|
|
|
@ -478,13 +478,8 @@ find_dline(struct sockaddr *addr, int aftype)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void find_exact_conf_by_address(const char*, int, const char *)
|
|
||||||
* Input:
|
|
||||||
* Output: ConfItem if found
|
|
||||||
* Side-effects: None
|
|
||||||
*/
|
|
||||||
struct ConfItem *
|
struct ConfItem *
|
||||||
find_exact_conf_by_address(const char *address, int type, const char *username)
|
find_exact_conf_by_address_filtered(const char *address, int type, const char *username, bool (*filter)(struct ConfItem *))
|
||||||
{
|
{
|
||||||
int masktype, bits;
|
int masktype, bits;
|
||||||
unsigned long hv;
|
unsigned long hv;
|
||||||
|
@ -514,6 +509,9 @@ find_exact_conf_by_address(const char *address, int type, const char *username)
|
||||||
arec->masktype == masktype &&
|
arec->masktype == masktype &&
|
||||||
(arec->username == NULL || username == NULL ? arec->username == username : !irccmp(arec->username, username)))
|
(arec->username == NULL || username == NULL ? arec->username == username : !irccmp(arec->username, username)))
|
||||||
{
|
{
|
||||||
|
if (filter && !filter(arec->aconf))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (masktype == HM_HOST)
|
if (masktype == HM_HOST)
|
||||||
{
|
{
|
||||||
if (!irccmp(arec->Mask.hostname, address))
|
if (!irccmp(arec->Mask.hostname, address))
|
||||||
|
@ -530,6 +528,17 @@ find_exact_conf_by_address(const char *address, int type, const char *username)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* void find_exact_conf_by_address(const char*, int, const char *)
|
||||||
|
* Input:
|
||||||
|
* Output: ConfItem if found
|
||||||
|
* Side-effects: None
|
||||||
|
*/
|
||||||
|
struct ConfItem *
|
||||||
|
find_exact_conf_by_address(const char *address, int type, const char *username)
|
||||||
|
{
|
||||||
|
return find_exact_conf_by_address_filtered(address, type, username, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* void add_conf_by_address(const char*, int, const char *,
|
/* void add_conf_by_address(const char*, int, const char *,
|
||||||
* struct ConfItem *aconf)
|
* struct ConfItem *aconf)
|
||||||
* Input:
|
* Input:
|
||||||
|
|
|
@ -81,10 +81,23 @@ static void apply_prop_kline(struct Client *source_p, struct ConfItem *aconf,
|
||||||
static bool already_placed_kline(struct Client *, const char *, const char *, int);
|
static bool already_placed_kline(struct Client *, const char *, const char *, int);
|
||||||
|
|
||||||
static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host);
|
static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host);
|
||||||
|
static void remove_superseded_klines(const char *user, const char *host);
|
||||||
static void remove_permkline_match(struct Client *, struct ConfItem *);
|
static void remove_permkline_match(struct Client *, struct ConfItem *);
|
||||||
static bool remove_temp_kline(struct Client *, struct ConfItem *);
|
static bool remove_temp_kline(struct Client *, struct ConfItem *);
|
||||||
static void remove_prop_kline(struct Client *, struct ConfItem *);
|
static void remove_prop_kline(struct Client *, struct ConfItem *);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_local_kline(struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
return aconf->lifetime == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_temporary_kline(struct ConfItem *aconf)
|
||||||
|
{
|
||||||
|
return aconf->lifetime == 0 && (aconf->flags & CONF_FLAGS_TEMPORARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* mo_kline()
|
/* mo_kline()
|
||||||
*
|
*
|
||||||
|
@ -209,6 +222,9 @@ mo_kline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
||||||
if(already_placed_kline(source_p, user, host, tkline_time))
|
if(already_placed_kline(source_p, user, host, tkline_time))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!propagated)
|
||||||
|
remove_superseded_klines(user, host);
|
||||||
|
|
||||||
rb_set_time();
|
rb_set_time();
|
||||||
aconf = make_conf();
|
aconf = make_conf();
|
||||||
aconf->status = CONF_KILL;
|
aconf->status = CONF_KILL;
|
||||||
|
@ -307,6 +323,8 @@ handle_remote_kline(struct Client *source_p, int tkline_time,
|
||||||
if(already_placed_kline(source_p, user, host, tkline_time))
|
if(already_placed_kline(source_p, user, host, tkline_time))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
remove_superseded_klines(user, host);
|
||||||
|
|
||||||
aconf = make_conf();
|
aconf = make_conf();
|
||||||
|
|
||||||
aconf->status = CONF_KILL;
|
aconf->status = CONF_KILL;
|
||||||
|
@ -418,25 +436,30 @@ mo_unkline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sour
|
||||||
cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN,
|
cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN,
|
||||||
"%s %s", user, host);
|
"%s %s", user, host);
|
||||||
|
|
||||||
if(aconf == NULL)
|
bool removed_kline = false;
|
||||||
|
|
||||||
|
while (aconf = find_exact_conf_by_address_filtered(host, CONF_KILL, user, is_local_kline), aconf != NULL)
|
||||||
{
|
{
|
||||||
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
|
removed_kline = true;
|
||||||
return;
|
|
||||||
|
if(remove_temp_kline(source_p, aconf))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
remove_permkline_match(source_p, aconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(aconf->lifetime)
|
aconf = find_exact_conf_by_address(host, CONF_KILL, user);
|
||||||
|
if (aconf)
|
||||||
{
|
{
|
||||||
if(propagated)
|
if (propagated)
|
||||||
remove_prop_kline(source_p, aconf);
|
remove_prop_kline(source_p, aconf);
|
||||||
else
|
else
|
||||||
sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
|
sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else if (!removed_kline)
|
||||||
if(remove_temp_kline(source_p, aconf))
|
{
|
||||||
return;
|
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
|
||||||
|
}
|
||||||
remove_permkline_match(source_p, aconf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ms_unkline()
|
/* ms_unkline()
|
||||||
|
@ -475,23 +498,22 @@ static void
|
||||||
handle_remote_unkline(struct Client *source_p, const char *user, const char *host)
|
handle_remote_unkline(struct Client *source_p, const char *user, const char *host)
|
||||||
{
|
{
|
||||||
struct ConfItem *aconf;
|
struct ConfItem *aconf;
|
||||||
|
bool removed_kline = false;
|
||||||
|
|
||||||
aconf = find_exact_conf_by_address(host, CONF_KILL, user);
|
while (aconf = find_exact_conf_by_address_filtered(host, CONF_KILL, user, is_local_kline), aconf != NULL)
|
||||||
if(aconf == NULL)
|
|
||||||
{
|
{
|
||||||
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
|
removed_kline = true;
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(aconf->lifetime)
|
|
||||||
{
|
|
||||||
sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(remove_temp_kline(source_p, aconf))
|
if(remove_temp_kline(source_p, aconf))
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
remove_permkline_match(source_p, aconf);
|
remove_permkline_match(source_p, aconf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (find_exact_conf_by_address(host, CONF_KILL, user))
|
||||||
|
sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
|
||||||
|
else if (!removed_kline)
|
||||||
|
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply_kline()
|
/* apply_kline()
|
||||||
|
@ -734,21 +756,46 @@ already_placed_kline(struct Client *source_p, const char *luser, const char *lho
|
||||||
aconf = NULL;
|
aconf = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(aconf != NULL)
|
|
||||||
{
|
if (aconf == NULL)
|
||||||
/* setting a tkline, or existing one is perm */
|
return false;
|
||||||
if(tkline || ((aconf->flags & CONF_FLAGS_TEMPORARY) == 0))
|
|
||||||
{
|
/* allow klines to be duplicated by longer ones */
|
||||||
|
if ((aconf->flags & CONF_FLAGS_TEMPORARY) &&
|
||||||
|
(tkline == 0 || tkline > aconf->hold - rb_current_time()))
|
||||||
|
return false;
|
||||||
|
|
||||||
reason = aconf->passwd ? aconf->passwd : "<No Reason>";
|
reason = aconf->passwd ? aconf->passwd : "<No Reason>";
|
||||||
|
|
||||||
sendto_one_notice(source_p,
|
sendto_one_notice(source_p,
|
||||||
":[%s@%s] already K-Lined by [%s@%s] - %s",
|
":[%s@%s] already K-Lined by [%s@%s] - %s",
|
||||||
luser, lhost, aconf->user, aconf->host, reason);
|
luser, lhost, aconf->user, aconf->host, reason);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
static void
|
||||||
|
remove_superseded_klines(const char *user, const char *host)
|
||||||
|
{
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
|
||||||
|
while (aconf = find_exact_conf_by_address_filtered(host, CONF_KILL, user, is_temporary_kline), aconf != NULL)
|
||||||
|
{
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < LAST_TEMP_TYPE; i++)
|
||||||
|
{
|
||||||
|
RB_DLINK_FOREACH(ptr, temp_klines[i].head)
|
||||||
|
{
|
||||||
|
if (aconf == ptr->data)
|
||||||
|
{
|
||||||
|
rb_dlinkDestroy(ptr, &temp_klines[i]);
|
||||||
|
delete_one_address_conf(aconf->host, aconf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove_permkline_match()
|
/* remove_permkline_match()
|
||||||
|
|
Loading…
Reference in a new issue