X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/4cb3ae7836bbb1dfcc5248875ca3c24fadff024e..8097430a810ac1535fe5304f74991b16ff58b064:/modules/m_resv.c diff --git a/modules/m_resv.c b/modules/m_resv.c index 75b73c6..af72747 100644 --- a/modules/m_resv.c +++ b/modules/m_resv.c @@ -38,6 +38,7 @@ #include "hash.h" #include "logger.h" #include "bandbi.h" +#include "operhash.h" static int mo_resv(struct Client *, struct Client *, int, const char **); static int ms_resv(struct Client *, struct Client *, int, const char **); @@ -61,14 +62,14 @@ mapi_clist_av1 resv_clist[] = { &resv_msgtab, &unresv_msgtab, NULL }; DECLARE_MODULE_AV1(resv, NULL, NULL, resv_clist, NULL, NULL, "$Revision$"); static void parse_resv(struct Client *source_p, const char *name, - const char *reason, int temp_time); + const char *reason, int temp_time, int propagated); static void propagate_resv(struct Client *source_p, const char *target, int temp_time, const char *name, const char *reason); static void cluster_resv(struct Client *source_p, int temp_time, const char *name, const char *reason); static void handle_remote_unresv(struct Client *source_p, const char *name); -static void remove_resv(struct Client *source_p, const char *name); +static void remove_resv(struct Client *source_p, const char *name, int propagated); /* * mo_resv() @@ -84,6 +85,7 @@ mo_resv(struct Client *client_p, struct Client *source_p, int parc, const char * const char *target_server = NULL; int temp_time; int loc = 1; + int propagated = ConfigFileEntry.use_propagated_bans; if(!IsOperResv(source_p)) { @@ -113,6 +115,9 @@ mo_resv(struct Client *client_p, struct Client *source_p, int parc, const char * target_server = parv[loc + 1]; loc += 2; + + /* Set as local-only. */ + propagated = 0; } if(parc <= loc || EmptyString(parv[loc])) @@ -131,10 +136,16 @@ mo_resv(struct Client *client_p, struct Client *source_p, int parc, const char * if(match(target_server, me.name) == 0) return 0; } - else if(rb_dlink_list_length(&cluster_conf_list) > 0) + else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0) cluster_resv(source_p, temp_time, name, reason); - parse_resv(source_p, name, reason, temp_time); + if(propagated && temp_time == 0) + { + sendto_one_notice(source_p, ":Cannot set a permanent global ban"); + return 0; + } + + parse_resv(source_p, name, reason, temp_time, propagated); return 0; } @@ -159,7 +170,7 @@ ms_resv(struct Client *client_p, struct Client *source_p, int parc, const char * if(!IsPerson(source_p)) return 0; - parse_resv(source_p, parv[2], parv[3], 0); + parse_resv(source_p, parv[2], parv[3], 0, 0); return 0; } @@ -170,7 +181,7 @@ me_resv(struct Client *client_p, struct Client *source_p, int parc, const char * if(!IsPerson(source_p)) return 0; - parse_resv(source_p, parv[2], parv[4], atoi(parv[1])); + parse_resv(source_p, parv[2], parv[4], atoi(parv[1]), 0); return 0; } @@ -183,7 +194,7 @@ me_resv(struct Client *client_p, struct Client *source_p, int parc, const char * * side effects - will parse the resv and create it if valid */ static void -parse_resv(struct Client *source_p, const char *name, const char *reason, int temp_time) +parse_resv(struct Client *source_p, const char *name, const char *reason, int temp_time, int propagated) { struct ConfItem *aconf; @@ -217,11 +228,36 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf = make_conf(); aconf->status = CONF_RESV_CHANNEL; aconf->port = 0; + aconf->created = rb_current_time(); aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); - add_to_resv_hash(aconf->host, aconf); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + + if(propagated) + { + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + aconf->hold = rb_current_time() + temp_time; + aconf->lifetime = aconf->hold; + replace_old_ban(aconf); + rb_dlinkAddAlloc(aconf, &prop_bans); - if(temp_time > 0) + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. RESV for [%s] [%s]", + get_oper_name(source_p), temp_time / 60, + name, reason); + ilog(L_KLINE, "R %s %d %s %s", + get_oper_name(source_p), temp_time / 60, name, reason); + sendto_one_notice(source_p, ":Added global %d min. RESV [%s]", + temp_time / 60, name); + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN R * %s %lu %d %d * :%s", + source_p->id, aconf->host, + (unsigned long)aconf->created, + (int)(aconf->hold - aconf->created), + (int)(aconf->lifetime - aconf->created), + reason); + } + else if(temp_time > 0) { aconf->hold = rb_current_time() + temp_time; @@ -245,6 +281,9 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te bandb_add(BANDB_RESV, source_p, aconf->host, NULL, aconf->passwd, NULL, 0); } + + add_to_resv_hash(aconf->host, aconf); + resv_chan_forcepart(aconf->host, aconf->passwd, temp_time); } else if(clean_resv_nick(name)) { @@ -279,11 +318,36 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf = make_conf(); aconf->status = CONF_RESV_NICK; aconf->port = 0; + aconf->created = rb_current_time(); aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); - rb_dlinkAddAlloc(aconf, &resv_conf_list); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + + if(propagated) + { + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + aconf->hold = rb_current_time() + temp_time; + aconf->lifetime = aconf->hold; + replace_old_ban(aconf); + rb_dlinkAddAlloc(aconf, &prop_bans); - if(temp_time > 0) + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. RESV for [%s] [%s]", + get_oper_name(source_p), temp_time / 60, + name, reason); + ilog(L_KLINE, "R %s %d %s %s", + get_oper_name(source_p), temp_time / 60, name, reason); + sendto_one_notice(source_p, ":Added global %d min. RESV [%s]", + temp_time / 60, name); + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN R * %s %lu %d %d * :%s", + source_p->id, aconf->host, + (unsigned long)aconf->created, + (int)(aconf->hold - aconf->created), + (int)(aconf->lifetime - aconf->created), + reason); + } + else if(temp_time > 0) { aconf->hold = rb_current_time() + temp_time; @@ -307,6 +371,8 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te bandb_add(BANDB_RESV, source_p, aconf->host, NULL, aconf->passwd, NULL, 0); } + + rb_dlinkAddAlloc(aconf, &resv_conf_list); } else sendto_one_notice(source_p, ":You have specified an invalid resv: [%s]", name); @@ -373,6 +439,8 @@ cluster_resv(struct Client *source_p, int temp_time, const char *name, const cha static int mo_unresv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { + int propagated = 1; + if(!IsOperResv(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "resv"); @@ -392,11 +460,16 @@ mo_unresv(struct Client *client_p, struct Client *source_p, int parc, const char if(match(parv[3], me.name) == 0) return 0; + + propagated = 0; } +#if 0 else if(rb_dlink_list_length(&cluster_conf_list) > 0) cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", parv[1]); +#endif + /* cluster{} moved to remove_resv */ - remove_resv(source_p, parv[1]); + remove_resv(source_p, parv[1], propagated); return 0; } @@ -441,40 +514,82 @@ handle_remote_unresv(struct Client *source_p, const char *name) source_p->servptr->name, SHARED_UNRESV)) return; - remove_resv(source_p, name); + remove_resv(source_p, name, 0); return; } static void -remove_resv(struct Client *source_p, const char *name) +remove_resv(struct Client *source_p, const char *name, int propagated) { struct ConfItem *aconf = NULL; + rb_dlink_node *ptr; if(IsChannelName(name)) { if((aconf = hash_find_resv(name)) == NULL) { + if(propagated && rb_dlink_list_length(&cluster_conf_list)) + cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); + sendto_one_notice(source_p, ":No RESV for %s", name); return; } + if(aconf->lifetime) + { + if(!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) + return; + sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the global RESV for: [%s]", + get_oper_name(source_p), name); + ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); + if(aconf->created < rb_current_time()) + aconf->created = rb_current_time(); + else + aconf->created++; + aconf->hold = aconf->created; + operhash_delete(aconf->info.oper); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN R * %s %lu %d %d * :*", + source_p->id, aconf->host, + (unsigned long)aconf->created, + 0, + (int)(aconf->lifetime - aconf->created)); + deactivate_conf(aconf, ptr); + return; + } + else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0) + cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", name); + + sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); if(!aconf->hold) + { bandb_del(BANDB_RESV, aconf->host, NULL); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the RESV for: [%s]", + get_oper_name(source_p), name); + } else { - sendto_one_notice(source_p, ":RESV for [%s] is removed", name); sendto_realops_snomask(SNO_GENERAL, L_ALL, - "%s has removed the RESV for: [%s]", + "%s has removed the temporary RESV for: [%s]", get_oper_name(source_p), name); - ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); } del_from_resv_hash(name, aconf); } else { - rb_dlink_node *ptr; - RB_DLINK_FOREACH(ptr, resv_conf_list.head) { aconf = ptr->data; @@ -487,19 +602,62 @@ remove_resv(struct Client *source_p, const char *name) if(aconf == NULL) { + if(propagated && rb_dlink_list_length(&cluster_conf_list)) + cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); + sendto_one_notice(source_p, ":No RESV for %s", name); return; } + if(aconf->lifetime) + { + if(!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) + return; + sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the global RESV for: [%s]", + get_oper_name(source_p), name); + ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); + if(aconf->created < rb_current_time()) + aconf->created = rb_current_time(); + else + aconf->created++; + aconf->hold = aconf->created; + operhash_delete(aconf->info.oper); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN R * %s %lu %d %d * :*", + source_p->id, aconf->host, + (unsigned long)aconf->created, + 0, + (int)(aconf->lifetime - aconf->created)); + deactivate_conf(aconf, ptr); + return; + } + else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0) + cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", name); + + sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); if(!aconf->hold) + { bandb_del(BANDB_RESV, aconf->host, NULL); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the RESV for: [%s]", + get_oper_name(source_p), name); + } else { - sendto_one_notice(source_p, ":RESV for [%s] is removed", name); sendto_realops_snomask(SNO_GENERAL, L_ALL, - "%s has removed the RESV for: [%s]", + "%s has removed the temporary RESV for: [%s]", get_oper_name(source_p), name); - ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); } /* already have ptr from the loop above.. */ rb_dlinkDestroy(ptr, &resv_conf_list);