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 remove_superseded_klines(const char *user, const char *host);
static void remove_permkline_match(struct Client *, struct ConfItem *);
static bool remove_temp_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()
*
}
reason = LOCAL_COPY(parv[loc]);
+ if(strlen(reason) > BANREASONLEN)
+ {
+ sendto_one_notice(source_p, ":K-Line reason exceeds %d characters", BANREASONLEN);
+ return;
+ }
if(parse_netmask_strict(host, NULL, NULL) == HM_ERROR)
{
if(target_server != NULL)
{
+ if (tkline_time)
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
+ "%s is adding a temporary %d min. K-Line for [%s@%s] on %s [%s]",
+ get_oper_name(source_p), tkline_time / 60, user, host, target_server, reason);
+ else
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
+ "%s is adding a K-Line for [%s@%s] on %s [%s]",
+ get_oper_name(source_p), user, host, target_server, reason);
+
propagate_generic(source_p, "KLINE", target_server, CAP_KLN,
"%d %s %s :%s", tkline_time, user, host, reason);
if(already_placed_kline(source_p, user, host, tkline_time))
return;
+ if (!propagated)
+ remove_superseded_klines(user, host);
+
rb_set_time();
aconf = make_conf();
aconf->status = CONF_KILL;
aconf->port = 0;
aconf->info.oper = operhash_add(get_oper_name(source_p));
- if(strlen(reason) > BANREASONLEN)
- reason[BANREASONLEN] = '\0';
-
/* Look for an oper reason */
if((oper_reason = strchr(reason, '|')) != NULL)
{
struct ConfItem *aconf = NULL;
char *oper_reason;
- if(!find_shared_conf(source_p->username, source_p->host,
- source_p->servptr->name,
- (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE))
- return;
-
if(!valid_user_host(source_p, user, host))
return;
if(already_placed_kline(source_p, user, host, tkline_time))
return;
+ remove_superseded_klines(user, host);
+
aconf = make_conf();
aconf->status = CONF_KILL;
return;
}
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is removing the K-Line for [%s@%s] on %s",
+ get_oper_name(source_p), user, host, parv[3]);
+
propagate_generic(source_p, "UNKLINE", parv[3], CAP_UNKLN, "%s %s", user, host);
if(match(parv[3], me.name) == 0)
cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN,
"%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);
- return;
+ removed_kline = true;
+
+ 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);
else
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))
- return;
-
- remove_permkline_match(source_p, aconf);
+ else if (!removed_kline)
+ {
+ sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
+ }
}
/* ms_unkline()
handle_remote_unkline(struct Client *source_p, const char *user, const char *host)
{
struct ConfItem *aconf;
+ bool removed_kline = false;
- if(!find_shared_conf(source_p->username, source_p->host,
- source_p->servptr->name, SHARED_UNKLINE))
- return;
-
- aconf = find_exact_conf_by_address(host, CONF_KILL, user);
- if(aconf == NULL)
+ 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);
- return;
- }
- if(aconf->lifetime)
- {
- sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
- return;
- }
+ removed_kline = true;
- if(remove_temp_kline(source_p, aconf))
- return;
+ if(remove_temp_kline(source_p, aconf))
+ 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()
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.. */
aconf = NULL;
}
}
- if(aconf != NULL)
+
+ if (aconf == NULL)
+ return false;
+
+ /* 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>";
+
+ sendto_one_notice(source_p,
+ ":[%s@%s] already K-Lined by [%s@%s] - %s",
+ luser, lhost, aconf->user, aconf->host, reason);
+ return true;
+}
+
+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)
{
- /* setting a tkline, or existing one is perm */
- if(tkline || ((aconf->flags & CONF_FLAGS_TEMPORARY) == 0))
- {
- reason = aconf->passwd ? aconf->passwd : "<No Reason>";
+ rb_dlink_node *ptr;
+ int i;
- sendto_one_notice(source_p,
- ":[%s@%s] already K-Lined by [%s@%s] - %s",
- luser, lhost, aconf->user, aconf->host, reason);
- return true;
+ 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;
+ }
+ }
}
}
-
- return false;
}
/* remove_permkline_match()
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",
0,
(int)(aconf->lifetime - aconf->created));
remove_reject_mask(aconf->user, aconf->host);
- deactivate_conf(aconf, ptr, now);
+ deactivate_conf(aconf, now);
}