From 1702b69419611c8e154b9c59c90b68ccdea59f56 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 14 Mar 2010 17:21:20 +0100 Subject: [PATCH 01/13] Add option general::use_propagated_bans to allow disabling new KLINE. If this option is yes (default), KLINE by itself sets global (propagated) bans. If this option is no, KLINE by itself sets a local kline following cluster{}, compatible with 3.2 and older versions. --- doc/example.conf | 1 + doc/reference.conf | 7 +++++++ include/s_conf.h | 1 + modules/m_info.c | 6 ++++++ modules/m_kline.c | 2 +- src/newconf.c | 1 + src/s_conf.c | 1 + 7 files changed, 18 insertions(+), 1 deletion(-) diff --git a/doc/example.conf b/doc/example.conf index 6a79129ee..4848ed04f 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -457,6 +457,7 @@ general { identify_command = "IDENTIFY"; non_redundant_klines = yes; warn_no_nline = yes; + use_propagated_bans = yes; stats_e_disabled = no; stats_c_oper_only=no; stats_h_oper_only=no; diff --git a/doc/reference.conf b/doc/reference.conf index 10971d4d5..ce2831092 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -1030,6 +1030,13 @@ general { */ warn_no_nline = yes; + /* use propagated bans: KLINE sets fully propagated bans. That means + * the klines are part of the netburst and restarted/split servers + * will get them, but they will not apply to 3.2 and older servers + * at all. + */ + use_propagated_bans = yes; + /* stats e disabled: disable stats e. useful if server ips are * exempted and you dont want them listing on irc. */ diff --git a/include/s_conf.h b/include/s_conf.h index 4cacc5e0c..03d78a668 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -223,6 +223,7 @@ struct config_file_entry int default_umodes; int global_snotices; int operspy_dont_care_user_info; + int use_propagated_bans; }; struct config_channel_entry diff --git a/modules/m_info.c b/modules/m_info.c index d3ddb3b88..3cdd7ba43 100644 --- a/modules/m_info.c +++ b/modules/m_info.c @@ -482,6 +482,12 @@ static struct InfoStruct info_table[] = { &ConfigFileEntry.warn_no_nline, "Display warning if connecting server lacks N-line" }, + { + "use_propagated_bans", + OUTPUT_BOOLEAN, + &ConfigFileEntry.use_propagated_bans, + "KLINE sets fully propagated bans" + }, { "default_split_server_count", OUTPUT_DECIMAL, diff --git a/modules/m_kline.c b/modules/m_kline.c index 46ff73040..364c30b0f 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -107,7 +107,7 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char struct ConfItem *aconf; int tkline_time = 0; int loc = 1; - int propagated = 1; + int propagated = ConfigFileEntry.use_propagated_bans; if(!IsOperK(source_p)) { diff --git a/src/newconf.c b/src/newconf.c index 24749a833..307d08905 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -2175,6 +2175,7 @@ static struct ConfEntry conf_general_table[] = { "ts_warn_delta", CF_TIME, NULL, 0, &ConfigFileEntry.ts_warn_delta }, { "use_whois_actually", CF_YESNO, NULL, 0, &ConfigFileEntry.use_whois_actually }, { "warn_no_nline", CF_YESNO, NULL, 0, &ConfigFileEntry.warn_no_nline }, + { "use_propagated_bans",CF_YESNO, NULL, 0, &ConfigFileEntry.use_propagated_bans }, { "\0", 0, NULL, 0, NULL } }; diff --git a/src/s_conf.c b/src/s_conf.c index 946380dbb..11d2d0a10 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -744,6 +744,7 @@ set_default_conf(void) ConfigFileEntry.collision_fnc = YES; ConfigFileEntry.global_snotices = YES; ConfigFileEntry.operspy_dont_care_user_info = NO; + ConfigFileEntry.use_propagated_bans = YES; #ifdef HAVE_LIBZ ConfigFileEntry.compression_level = 4; From 34e02db66b456813054bbcc255791782ade48946 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Tue, 16 Mar 2010 19:13:09 +0100 Subject: [PATCH 02/13] Fix a signedness comparison warning. --- modules/m_cap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/m_cap.c b/modules/m_cap.c index 94aebaca8..6e06ef73c 100644 --- a/modules/m_cap.c +++ b/modules/m_cap.c @@ -174,7 +174,7 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clea char *p; int buflen = 0; int curlen, mlen; - int i; + size_t i; mlen = rb_sprintf(buf, ":%s CAP %s %s", me.name, From 3cbbfb2556d8f04c8c8895372fd815158f850ee1 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Tue, 16 Mar 2010 23:05:50 +0100 Subject: [PATCH 03/13] Add propagated xlines, like klines. --- doc/reference.conf | 8 ++-- help/opers/stats | 2 +- include/s_conf.h | 1 + modules/core/m_ban.c | 25 +++++++++-- modules/m_kline.c | 23 +--------- modules/m_xline.c | 104 +++++++++++++++++++++++++++++++++++++------ src/s_conf.c | 30 +++++++++++++ 7 files changed, 149 insertions(+), 44 deletions(-) diff --git a/doc/reference.conf b/doc/reference.conf index ce2831092..6074ed0fd 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -1030,10 +1030,10 @@ general { */ warn_no_nline = yes; - /* use propagated bans: KLINE sets fully propagated bans. That means - * the klines are part of the netburst and restarted/split servers - * will get them, but they will not apply to 3.2 and older servers - * at all. + /* use propagated bans: KLINE and XLINE set fully propagated bans. + * That means the bans are part of the netburst and restarted/split + * servers will get them, but they will not apply to 3.2 and older + * servers at all. */ use_propagated_bans = yes; diff --git a/help/opers/stats b/help/opers/stats index 5d25900da..f20ad5645 100644 --- a/help/opers/stats +++ b/help/opers/stats @@ -36,7 +36,7 @@ X f - Shows File Descriptors * U - Shows shared blocks (Old U: lines) u - Shows server uptime ^ v - Shows connected servers and brief status information -* x - Shows temporary gecos bans +* x - Shows temporary and global gecos bans * X - Shows gecos bans (Old X: lines) ^ y - Shows connection classes (Old Y: lines) * z - Shows memory stats diff --git a/include/s_conf.h b/include/s_conf.h index 03d78a668..b1124f0b9 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -327,6 +327,7 @@ 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 *); +extern void replace_old_ban(struct ConfItem *); extern void read_conf_files(int cold); diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index f61ba0763..0efe6ef3e 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -89,6 +89,10 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p ntype = CONF_KILL; stype = "K-Line"; break; + case 'X': + ntype = CONF_XLINE; + stype = "X-Line"; + break; default: sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unknown BAN type %s from %s", @@ -199,10 +203,12 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->user ? "@" : "", aconf->host, parv[parc - 1]); - ilog(L_KLINE, "%s %s %d %s %s %s", parv[1], + ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), (hold - rb_current_time()) / 60, - aconf->user, aconf->host, + aconf->user ? aconf->user : "", + aconf->user ? " " : "", + aconf->host, parv[parc - 1]); aconf->status &= ~CONF_ILLEGAL; } @@ -217,9 +223,11 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->host, strcmp(parv[7], "*") ? " on behalf of " : "", strcmp(parv[7], "*") ? parv[7] : ""); - ilog(L_KLINE, "U%s %s %s %s", parv[1], + ilog(L_KLINE, "U%s %s %s%s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), - aconf->user, aconf->host); + aconf->user ? aconf->user : "", + aconf->user ? " " : "", + aconf->host); } switch (ntype) { @@ -244,6 +252,15 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p check_klines(); } break; + case CONF_XLINE: + if (aconf->status & CONF_ILLEGAL) + remove_reject_mask(aconf->host, NULL); + else + { + rb_dlinkAddAlloc(aconf, &xline_conf_list); + check_xlines(); + } + break; } sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS, ":%s BAN %s %s %s %s %s %s %s :%s", diff --git a/modules/m_kline.c b/modules/m_kline.c index 364c30b0f..d6e22bc58 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -584,32 +584,11 @@ static void apply_prop_kline(struct Client *source_p, struct ConfItem *aconf, const char *reason, const char *oper_reason, int tkline_time) { - rb_dlink_node *ptr; - struct ConfItem *oldconf; - aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; aconf->hold = rb_current_time() + tkline_time; aconf->lifetime = aconf->hold; - ptr = find_prop_ban(aconf->status, aconf->user, aconf->host); - if(ptr != NULL) - { - oldconf = ptr->data; - /* Remember at least as long as the old one. */ - if(oldconf->lifetime > aconf->lifetime) - aconf->lifetime = oldconf->lifetime; - /* Force creation time to increase. */ - if(oldconf->created >= aconf->created) - aconf->created = oldconf->created + 1; - /* Leave at least one second of validity. */ - if(aconf->hold <= aconf->created) - aconf->hold = aconf->created + 1; - if(aconf->lifetime < aconf->hold) - aconf->lifetime = aconf->hold; - /* Tell deactivate_conf() to destroy it. */ - oldconf->lifetime = rb_current_time(); - deactivate_conf(oldconf, ptr); - } + replace_old_ban(aconf); rb_dlinkAddAlloc(aconf, &prop_bans); add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf); diff --git a/modules/m_xline.c b/modules/m_xline.c index 556ad005c..566a36928 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -79,7 +79,7 @@ DECLARE_MODULE_AV1(xline, NULL, NULL, xline_clist, NULL, NULL, "$Revision$"); static int valid_xline(struct Client *, const char *, const char *); static void apply_xline(struct Client *client_p, const char *name, - const char *reason, int temp_time); + const char *reason, int temp_time, int propagated); static void propagate_xline(struct Client *source_p, const char *target, int temp_time, const char *name, const char *type, const char *reason); static void cluster_xline(struct Client *source_p, int temp_time, @@ -89,7 +89,8 @@ static void handle_remote_xline(struct Client *source_p, int temp_time, const char *name, const char *reason); static void handle_remote_unxline(struct Client *source_p, const char *name); -static void remove_xline(struct Client *source_p, const char *name); +static void remove_xline(struct Client *source_p, const char *name, + int propagated); /* m_xline() @@ -107,6 +108,7 @@ mo_xline(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(!IsOperXline(source_p)) { @@ -152,8 +154,11 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char if(!match(target_server, me.name)) return 0; + + /* Set as local-only. */ + propagated = 0; } - else if(rb_dlink_list_length(&cluster_conf_list) > 0) + else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0) cluster_xline(source_p, temp_time, name, reason); if((aconf = find_xline_mask(name)) != NULL) @@ -166,7 +171,13 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char if(!valid_xline(source_p, name, reason)) return 0; - apply_xline(source_p, name, reason, temp_time); + if(propagated && temp_time == 0) + { + sendto_one_notice(source_p, ":Cannot set a permanent global ban"); + return 0; + } + + apply_xline(source_p, name, reason, temp_time, propagated); return 0; } @@ -226,7 +237,7 @@ handle_remote_xline(struct Client *source_p, int temp_time, const char *name, co return; } - apply_xline(source_p, name, reason, temp_time); + apply_xline(source_p, name, reason, temp_time, 0); } /* valid_xline() @@ -270,8 +281,9 @@ valid_xline(struct Client *source_p, const char *gecos, const char *reason) } void -apply_xline(struct Client *source_p, const char *name, const char *reason, int temp_time) +apply_xline(struct Client *source_p, const char *name, const char *reason, int temp_time, int propagated) { + rb_dlink_node *ptr; struct ConfItem *aconf; aconf = make_conf(); @@ -283,7 +295,32 @@ apply_xline(struct Client *source_p, const char *name, const char *reason, int t aconf->info.oper = operhash_add(get_oper_name(source_p)); - if(temp_time > 0) + 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); + + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. X-Line for [%s] [%s]", + get_oper_name(source_p), temp_time / 60, + aconf->host, reason); + ilog(L_KLINE, "X %s %d %s %s", + get_oper_name(source_p), temp_time / 60, name, reason); + sendto_one_notice(source_p, ":Added global %d min. X-Line [%s]", + temp_time / 60, aconf->host); + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN X * %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; @@ -366,6 +403,8 @@ cluster_xline(struct Client *source_p, int temp_time, const char *name, const ch static int mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { + int propagated = 1; + if(!IsOperXline(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "xline"); @@ -385,11 +424,12 @@ mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const cha if(match(parv[3], me.name) == 0) return 0; - } - else if(rb_dlink_list_length(&cluster_conf_list)) - cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", parv[1]); - remove_xline(source_p, parv[1]); + propagated = 0; + } + /* cluster{} moved to remove_xline */ + + remove_xline(source_p, parv[1], propagated); return 0; } @@ -434,13 +474,13 @@ handle_remote_unxline(struct Client *source_p, const char *name) source_p->servptr->name, SHARED_UNXLINE)) return; - remove_xline(source_p, name); + remove_xline(source_p, name, 0); return; } static void -remove_xline(struct Client *source_p, const char *name) +remove_xline(struct Client *source_p, const char *name, int propagated) { struct ConfItem *aconf; rb_dlink_node *ptr; @@ -451,6 +491,41 @@ remove_xline(struct Client *source_p, const char *name) if(!irccmp(aconf->host, name)) { + if(aconf->lifetime) + { + if(!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) + return; + sendto_one_notice(source_p, ":X-Line for [%s] is removed", name); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the global X-Line for: [%s]", + get_oper_name(source_p), name); + ilog(L_KLINE, "UX %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 X * %s %lu %d %d * :*", + source_p->id, aconf->host, + (unsigned long)aconf->created, + 0, + (int)(aconf->lifetime - aconf->created)); + remove_reject_mask(aconf->host, NULL); + deactivate_conf(aconf, ptr); + return; + } + else if(MyClient(source_p) && rb_dlink_list_length(&cluster_conf_list)) + cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); if(!aconf->hold) { bandb_del(BANDB_XLINE, aconf->host, NULL); @@ -477,6 +552,9 @@ remove_xline(struct Client *source_p, const char *name) } } + if(MyClient(source_p) && rb_dlink_list_length(&cluster_conf_list)) + cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); + sendto_one_notice(source_p, ":No X-Line for %s", name); return; diff --git a/src/s_conf.c b/src/s_conf.c index 11d2d0a10..cfd6048d4 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -1064,6 +1064,36 @@ deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr) } } +/* Given a new ban ConfItem, look for any matching ban, update the lifetime + * from it and delete it. + */ +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 = ptr->data; + /* Remember at least as long as the old one. */ + if(oldconf->lifetime > aconf->lifetime) + aconf->lifetime = oldconf->lifetime; + /* Force creation time to increase. */ + if(oldconf->created >= aconf->created) + aconf->created = oldconf->created + 1; + /* Leave at least one second of validity. */ + if(aconf->hold <= aconf->created) + aconf->hold = aconf->created + 1; + if(aconf->lifetime < aconf->hold) + aconf->lifetime = aconf->hold; + /* Tell deactivate_conf() to destroy it. */ + oldconf->lifetime = rb_current_time(); + deactivate_conf(oldconf, ptr); + } +} + static void expire_prop_bans(void *list) { From f89191ace9a0010419aadcf8ceba0d93f694d3f8 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Thu, 18 Mar 2010 00:22:35 +0100 Subject: [PATCH 04/13] BAN: xlines do not have oper reasons, their "reason" is already oper only. --- modules/core/m_ban.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index 0efe6ef3e..1fecd3f14 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -157,8 +157,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->info.oper = operhash_add(oper); aconf->created = created; aconf->hold = hold; - p = strchr(parv[parc - 1], '|'); - if (p == NULL) + if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL) aconf->passwd = rb_strdup(parv[parc - 1]); else { From a812a239c8d9ed2c58a6b948e552655961ea7233 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Mar 2010 02:06:29 +0100 Subject: [PATCH 05/13] Remove unused variable. --- modules/m_xline.c | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/m_xline.c b/modules/m_xline.c index 566a36928..315a686f3 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -283,7 +283,6 @@ valid_xline(struct Client *source_p, const char *gecos, const char *reason) void apply_xline(struct Client *source_p, const char *name, const char *reason, int temp_time, int propagated) { - rb_dlink_node *ptr; struct ConfItem *aconf; aconf = make_conf(); From 1b5d7c2e8aec5f9bbcf11221c80a7bbf1ceb9b0e Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Mar 2010 16:09:26 +0100 Subject: [PATCH 06/13] XLINE: Do not cluster unxlines ON specific servers. This bug was introduced with BAN support for XLINE. --- modules/m_xline.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/m_xline.c b/modules/m_xline.c index 315a686f3..d1975ecdb 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -523,7 +523,7 @@ remove_xline(struct Client *source_p, const char *name, int propagated) deactivate_conf(aconf, ptr); return; } - else if(MyClient(source_p) && rb_dlink_list_length(&cluster_conf_list)) + else if(propagated && rb_dlink_list_length(&cluster_conf_list)) cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name); if(!aconf->hold) { @@ -551,7 +551,7 @@ remove_xline(struct Client *source_p, const char *name, int propagated) } } - if(MyClient(source_p) && rb_dlink_list_length(&cluster_conf_list)) + 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 X-Line for %s", name); From dca9e552570ccbd56ffde317a13266d75f88a06a Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Mar 2010 16:13:57 +0100 Subject: [PATCH 07/13] Add propagated resvs, like klines and xlines. --- doc/reference.conf | 2 +- help/opers/stats | 2 +- include/channel.h | 2 + modules/core/m_ban.c | 35 ++++++- modules/m_resv.c | 228 ++++++++++++++++++++++++++++++------------- src/channel.c | 51 ++++++++++ 6 files changed, 245 insertions(+), 75 deletions(-) diff --git a/doc/reference.conf b/doc/reference.conf index 6074ed0fd..d71cd0b00 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -1030,7 +1030,7 @@ general { */ warn_no_nline = yes; - /* use propagated bans: KLINE and XLINE set fully propagated bans. + /* use propagated bans: KLINE, XLINE and RESV set fully propagated bans. * That means the bans are part of the netburst and restarted/split * servers will get them, but they will not apply to 3.2 and older * servers at all. diff --git a/help/opers/stats b/help/opers/stats index f20ad5645..fb7bb347f 100644 --- a/help/opers/stats +++ b/help/opers/stats @@ -29,7 +29,7 @@ X f - Shows File Descriptors ^ o - Shows operator blocks (Old O: lines) ^ P - Shows configured ports p - Shows online opers -* q - Shows temporary resv'd nicks and channels +* q - Shows temporary and global resv'd nicks and channels * Q - Shows resv'd nicks and channels * r - Shows resource usage by ircd * t - Shows generic server stats diff --git a/include/channel.h b/include/channel.h index 090f76590..466e94a10 100644 --- a/include/channel.h +++ b/include/channel.h @@ -257,6 +257,8 @@ extern void unset_chcap_usage_counts(struct Client *serv_p); extern void send_cap_mode_changes(struct Client *client_p, struct Client *source_p, struct Channel *chptr, struct ChModeChange foo[], int); +void resv_chan_forcepart(const char *name, const char *reason, int temp_time); + extern void set_channel_mode(struct Client *client_p, struct Client *source_p, struct Channel *chptr, struct membership *msptr, int parc, const char *parv[]); extern void set_channel_mlock(struct Client *client_p, struct Client *source_p, diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index 1fecd3f14..8481282d5 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -29,6 +29,7 @@ #include "stdinc.h" #include "send.h" +#include "channel.h" #include "client.h" #include "common.h" #include "config.h" @@ -75,6 +76,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p time_t created, hold, lifetime; char *p; int act; + int valid; if (strlen(parv[1]) != 1) { @@ -93,6 +95,11 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p ntype = CONF_XLINE; stype = "X-Line"; break; + case 'R': + ntype = IsChannelName(parv[3]) ? CONF_RESV_CHANNEL : + CONF_RESV_NICK; + stype = "RESV"; + break; default: sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unknown BAN type %s from %s", @@ -164,10 +171,19 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1); aconf->spasswd = rb_strdup(p + 1); } - if (act && hold != created && - !(ntype == CONF_KILL ? - valid_wild_card(aconf->user, aconf->host) : - valid_wild_card_simple(aconf->host))) + switch (ntype) + { + case CONF_KILL: + valid = valid_wild_card(aconf->user, aconf->host); + break; + case CONF_RESV_CHANNEL: + valid = 1; + break; + default: + valid = valid_wild_card_simple(aconf->host); + break; + } + if (act && hold != created && !valid) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters", @@ -260,6 +276,17 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p check_xlines(); } break; + case CONF_RESV_CHANNEL: + if (!(aconf->status & CONF_ILLEGAL)) + { + add_to_resv_hash(aconf->host, aconf); + resv_chan_forcepart(aconf->host, aconf->passwd, hold - rb_current_time()); + } + break; + case CONF_RESV_NICK: + if (!(aconf->status & CONF_ILLEGAL)) + rb_dlinkAddAlloc(aconf, &resv_conf_list); + break; } sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS, ":%s BAN %s %s %s %s %s %s %s :%s", diff --git a/modules/m_resv.c b/modules/m_resv.c index 01b41b799..cdcaecbbc 100644 --- a/modules/m_resv.c +++ b/modules/m_resv.c @@ -62,15 +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 resv_chan_forcepart(const char *name, const char *reason, int temp_time); +static void remove_resv(struct Client *source_p, const char *name, int propagated); /* * mo_resv() @@ -86,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)) { @@ -115,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])) @@ -133,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; } @@ -161,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; } @@ -172,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; } @@ -185,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; @@ -223,10 +232,32 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); aconf->info.oper = operhash_add(get_oper_name(source_p)); - add_to_resv_hash(aconf->host, aconf); - resv_chan_forcepart(aconf->host, aconf->passwd, temp_time); - if(temp_time > 0) + 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); + + 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; @@ -250,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)) { @@ -288,9 +322,32 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); aconf->info.oper = operhash_add(get_oper_name(source_p)); - rb_dlinkAddAlloc(aconf, &resv_conf_list); - if(temp_time > 0) + 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); + + 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; @@ -314,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); @@ -380,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"); @@ -399,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; } @@ -448,24 +514,63 @@ 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) @@ -485,8 +590,6 @@ remove_resv(struct Client *source_p, const char *name) } else { - rb_dlink_node *ptr; - RB_DLINK_FOREACH(ptr, resv_conf_list.head) { aconf = ptr->data; @@ -499,10 +602,48 @@ 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); + if(!aconf->hold) bandb_del(BANDB_RESV, aconf->host, NULL); else @@ -520,54 +661,3 @@ remove_resv(struct Client *source_p, const char *name) return; } - -static void -resv_chan_forcepart(const char *name, const char *reason, int temp_time) -{ - rb_dlink_node *ptr; - rb_dlink_node *next_ptr; - struct Channel *chptr; - struct membership *msptr; - struct Client *target_p; - - if(!ConfigChannel.resv_forcepart) - return; - - /* for each user on our server in the channel list - * send them a PART, and notify opers. - */ - chptr = find_channel(name); - if(chptr != NULL) - { - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head) - { - msptr = ptr->data; - target_p = msptr->client_p; - - if(IsExemptResv(target_p)) - continue; - - sendto_server(target_p, chptr, CAP_TS6, NOCAPS, - ":%s PART %s", target_p->id, chptr->chname); - - sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s", - target_p->name, target_p->username, - target_p->host, chptr->chname, target_p->name); - - remove_user_from_channel(msptr); - - /* notify opers & user they were removed from the channel */ - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Forced PART for %s!%s@%s from %s (%s)", - target_p->name, target_p->username, - target_p->host, name, reason); - - if(temp_time > 0) - sendto_one_notice(target_p, ":*** Channel %s is temporarily unavailable on this server.", - name); - else - sendto_one_notice(target_p, ":*** Channel %s is no longer available on this server.", - name); - } - } -} diff --git a/src/channel.c b/src/channel.c index 7483b6e50..1a159f147 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1358,3 +1358,54 @@ send_cap_mode_changes(struct Client *client_p, struct Client *source_p, sendto_server(client_p, chptr, cap, nocap, "%s %s", modebuf, parabuf); } } + +void +resv_chan_forcepart(const char *name, const char *reason, int temp_time) +{ + rb_dlink_node *ptr; + rb_dlink_node *next_ptr; + struct Channel *chptr; + struct membership *msptr; + struct Client *target_p; + + if(!ConfigChannel.resv_forcepart) + return; + + /* for each user on our server in the channel list + * send them a PART, and notify opers. + */ + chptr = find_channel(name); + if(chptr != NULL) + { + RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head) + { + msptr = ptr->data; + target_p = msptr->client_p; + + if(IsExemptResv(target_p)) + continue; + + sendto_server(target_p, chptr, CAP_TS6, NOCAPS, + ":%s PART %s", target_p->id, chptr->chname); + + sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s", + target_p->name, target_p->username, + target_p->host, chptr->chname, target_p->name); + + remove_user_from_channel(msptr); + + /* notify opers & user they were removed from the channel */ + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "Forced PART for %s!%s@%s from %s (%s)", + target_p->name, target_p->username, + target_p->host, name, reason); + + if(temp_time > 0) + sendto_one_notice(target_p, ":*** Channel %s is temporarily unavailable on this server.", + name); + else + sendto_one_notice(target_p, ":*** Channel %s is no longer available on this server.", + name); + } + } +} From 5bd874eb41bcae9fb69abfeab28a4d81b83ce4a0 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Mar 2010 16:24:13 +0100 Subject: [PATCH 08/13] Restore snotes, logs for UNRESV nick. This bug was introduced when adding bandb. --- modules/m_resv.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/m_resv.c b/modules/m_resv.c index cdcaecbbc..af727478d 100644 --- a/modules/m_resv.c +++ b/modules/m_resv.c @@ -644,15 +644,20 @@ remove_resv(struct Client *source_p, const char *name, int propagated) 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); - else { - sendto_one_notice(source_p, ":RESV for [%s] is removed", name); + 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); - ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name); + } + else + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the temporary RESV for: [%s]", + get_oper_name(source_p), name); } /* already have ptr from the loop above.. */ rb_dlinkDestroy(ptr, &resv_conf_list); From 803ce385bfce304cb5ca4f8e370d003b9cd01287 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 27 Mar 2010 20:09:46 +0100 Subject: [PATCH 09/13] Fix various compiler warnings. --- modules/core/m_ban.c | 6 +++--- modules/m_kline.c | 2 +- src/s_conf.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/core/m_ban.c b/modules/core/m_ban.c index 8481282d5..d966edd4a 100644 --- a/modules/core/m_ban.c +++ b/modules/core/m_ban.c @@ -187,7 +187,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters", - (hold - rb_current_time()) / 60, + (int)((hold - rb_current_time()) / 60), stype, IsServer(source_p) ? source_p->name : get_oper_name(source_p), strcmp(parv[7], "*") ? " on behalf of " : "", @@ -210,7 +210,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s added global %d min. %s%s%s for [%s%s%s] [%s]", IsServer(source_p) ? source_p->name : get_oper_name(source_p), - (hold - rb_current_time()) / 60, + (int)((hold - rb_current_time()) / 60), stype, strcmp(parv[7], "*") ? " from " : "", strcmp(parv[7], "*") ? parv[7] : "", @@ -220,7 +220,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p parv[parc - 1]); ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), - (hold - rb_current_time()) / 60, + (int)((hold - rb_current_time()) / 60), aconf->user ? aconf->user : "", aconf->user ? " " : "", aconf->host, diff --git a/modules/m_kline.c b/modules/m_kline.c index d6e22bc58..89ba23533 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -297,7 +297,7 @@ handle_remote_kline(struct Client *source_p, int tkline_time, ":Please include at least %d non-wildcard " "characters with the user@host", ConfigFileEntry.min_nonwildcard); - return 0; + return; } if(already_placed_kline(source_p, user, host, tkline_time)) diff --git a/src/s_conf.c b/src/s_conf.c index cfd6048d4..dc733430f 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -1261,7 +1261,7 @@ get_user_ban_reason(struct ConfItem *aconf) rb_snprintf(reasonbuf, sizeof reasonbuf, "Temporary %c-line %d min. - ", aconf->status == CONF_DLINE ? 'D' : 'K', - (aconf->hold - aconf->created) / 60); + (int)((aconf->hold - aconf->created) / 60)); else reasonbuf[0] = '\0'; if (aconf->passwd) From 4c3f0955bf82689c4e25c07e64f1e29ea5d834b0 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Sun, 28 Mar 2010 03:04:59 -0400 Subject: [PATCH 10/13] Add help for MODRELOAD. --- help/opers/index | 26 +++++++++++++------------- help/opers/modreload | 6 ++++++ 2 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 help/opers/modreload diff --git a/help/opers/index b/help/opers/index index 673c1762a..56171ec4c 100644 --- a/help/opers/index +++ b/help/opers/index @@ -8,16 +8,16 @@ HELP INDEX INFO INVITE ISON JOIN KICK KILL KLINE KNOCK LINKS LIST LOCOPS LUSERS MAP MASKTRACE -MODLIST MODLOAD MODRESTART MODUNLOAD -MOTD NAMES NICK NOTICE -OPER OPERSPY OPERWALL PART -PASS PING PONG POST -PRIVMSG QUIT REHASH RESTART -RESV SCAN SERVER SET -SJOIN SNOMASK SQUIT STATS -SVINFO TESTGECOS TESTLINE TESTMASK -TIME TOPIC TRACE UHELP -UMODE UNDLINE UNKLINE UNREJECT -UNRESV UNXLINE USER USERHOST -USERS VERSION WALLOPS WHO -WHOIS WHOWAS XLINE +MODLIST MODLOAD MODRELOAD MODRESTART +MODUNLOAD MOTD NAMES NICK +NOTICE OPER OPERSPY OPERWALL +PART PASS PING PONG +POST PRIVMSG QUIT REHASH +RESTART RESV SCAN SERVER +SET SJOIN SNOMASK SQUIT +STATS SVINFO TESTGECOS TESTLINE +TESTMASK TIME TOPIC TRACE +UHELP UMODE UNDLINE UNKLINE +UNREJECT UNRESV UNXLINE USER +USERHOST USERS VERSION WALLOPS +WHO WHOIS WHOWAS XLINE diff --git a/help/opers/modreload b/help/opers/modreload new file mode 100644 index 000000000..96abca29f --- /dev/null +++ b/help/opers/modreload @@ -0,0 +1,6 @@ +MODRELOAD + +-- Reload a module in the ircd +Use just the module name, the path is not needed. + +- Requires Oper Priv: A From 19716b9fd628aa55842e13f7996175d0bb276c54 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Thu, 1 Apr 2010 01:16:16 +0200 Subject: [PATCH 11/13] New custom channel mode API allowing reloading such modules. Additionally, attempting to use too many modes or two times the same letter is now detected and prevented. Modules now request that a channel mode be added/orphaned, instead of ugly manipulation from which that request had to be guessed. Slight changes are needed to modules that provide channel modes. From the old API, one important function has been made static, the other important function has been renamed, so loading old modules should fail safely. --- extensions/chm_adminonly.c | 15 ++++++------ extensions/chm_operonly.c | 21 +++++----------- extensions/chm_sslonly.c | 15 ++++++------ include/channel.h | 8 ++++--- include/chmode.h | 6 ++--- src/chmode.c | 49 +++++++++++++++++++++++--------------- src/ircd.c | 8 +------ 7 files changed, 59 insertions(+), 63 deletions(-) diff --git a/extensions/chm_adminonly.c b/extensions/chm_adminonly.c index 9380c3df7..c478e91e5 100644 --- a/extensions/chm_adminonly.c +++ b/extensions/chm_adminonly.c @@ -17,13 +17,14 @@ mapi_hfn_list_av1 adminonly_hfnlist[] = { { NULL, NULL } }; +static unsigned int mymode; + static int _modinit(void) { - chmode_table['A'].mode_type = find_cflag_slot(); - chmode_table['A'].set_func = chm_staff; - - construct_noparam_modes(); + mymode = cflag_add('A', chm_staff); + if (mymode == 0) + return -1; return 0; } @@ -31,9 +32,7 @@ _modinit(void) static void _moddeinit(void) { - chmode_table['A'].mode_type = 0; - - construct_noparam_modes(); + cflag_orphan('A'); } DECLARE_MODULE_AV1(chm_adminonly, _modinit, _moddeinit, NULL, NULL, adminonly_hfnlist, "$Revision$"); @@ -44,7 +43,7 @@ h_can_join(hook_data_channel *data) struct Client *source_p = data->client; struct Channel *chptr = data->chptr; - if((chptr->mode.mode & chmode_flags['A']) && !IsAdmin(source_p)) { + if((chptr->mode.mode & mymode) && !IsAdmin(source_p)) { sendto_one_numeric(source_p, 519, "%s :Cannot join channel (+A) - you are not an IRC server administrator", chptr->chname); data->approved = ERR_CUSTOM; } diff --git a/extensions/chm_operonly.c b/extensions/chm_operonly.c index 4912e5a74..5cb87ab31 100644 --- a/extensions/chm_operonly.c +++ b/extensions/chm_operonly.c @@ -17,7 +17,7 @@ mapi_hfn_list_av1 operonly_hfnlist[] = { { NULL, NULL } }; - +static unsigned int mymode; /* This is a simple example of how to use dynamic channel modes. * Not tested enough yet, use at own risk. @@ -26,27 +26,18 @@ mapi_hfn_list_av1 operonly_hfnlist[] = { static int _modinit(void) { - /* add the channel mode to the available slot */ - chmode_table['O'].mode_type = find_cflag_slot(); - chmode_table['O'].set_func = chm_staff; - - construct_noparam_modes(); + mymode = cflag_add('O', chm_staff); + if (mymode == 0) + return -1; return 0; } -/* Well, the first ugly thing is that we changle chmode_table in _modinit - * and chmode_flags in _moddeinit (different arrays) - must be fixed. - * -- dwr - */ static void _moddeinit(void) { - /* disable the channel mode and remove it from the available list */ - chmode_table['O'].mode_type = 0; - - construct_noparam_modes(); + cflag_orphan('O'); } DECLARE_MODULE_AV1(chm_operonly, _modinit, _moddeinit, NULL, NULL, operonly_hfnlist, "$Revision$"); @@ -57,7 +48,7 @@ h_can_join(hook_data_channel *data) struct Client *source_p = data->client; struct Channel *chptr = data->chptr; - if((chptr->mode.mode & chmode_flags['O']) && !IsOper(source_p)) { + if((chptr->mode.mode & mymode) && !IsOper(source_p)) { sendto_one_numeric(source_p, 520, "%s :Cannot join channel (+O) - you are not an IRC operator", chptr->chname); data->approved = ERR_CUSTOM; } diff --git a/extensions/chm_sslonly.c b/extensions/chm_sslonly.c index 197aac699..2808bb18a 100644 --- a/extensions/chm_sslonly.c +++ b/extensions/chm_sslonly.c @@ -17,13 +17,14 @@ mapi_hfn_list_av1 sslonly_hfnlist[] = { { NULL, NULL } }; +static unsigned int mymode; + static int _modinit(void) { - chmode_table['S'].mode_type = find_cflag_slot(); - chmode_table['S'].set_func = chm_simple; - - construct_noparam_modes(); + mymode = cflag_add('S', chm_simple); + if (mymode == 0) + return -1; return 0; } @@ -32,9 +33,7 @@ _modinit(void) static void _moddeinit(void) { - chmode_table['S'].mode_type = 0; - - construct_noparam_modes(); + cflag_orphan('S'); } DECLARE_MODULE_AV1(chm_sslonly, _modinit, _moddeinit, NULL, NULL, sslonly_hfnlist, "$Revision$"); @@ -45,7 +44,7 @@ h_can_join(hook_data_channel *data) struct Client *source_p = data->client; struct Channel *chptr = data->chptr; - if((chptr->mode.mode & chmode_flags['S']) && !IsSSLClient(source_p)) { + if((chptr->mode.mode & mymode) && !IsSSLClient(source_p)) { sendto_one_notice(source_p, ":Only users using SSL could join this channel!"); data->approved = ERR_CUSTOM; } diff --git a/include/channel.h b/include/channel.h index 466e94a10..923871ed2 100644 --- a/include/channel.h +++ b/include/channel.h @@ -126,11 +126,13 @@ struct ChCapCombo int cap_no; }; +typedef void (*ChannelModeFunc)(struct Client *source_p, struct Channel *chptr, + int alevel, int parc, int *parn, + const char **parv, int *errors, int dir, char c, long mode_type); + struct ChannelMode { - void (*set_func) (struct Client * source_p, struct Channel * chptr, - int alevel, int parc, int *parn, - const char **parv, int *errors, int dir, char c, long mode_type); + ChannelModeFunc set_func; long mode_type; }; diff --git a/include/chmode.h b/include/chmode.h index a9c04a64e..f30c9bf39 100644 --- a/include/chmode.h +++ b/include/chmode.h @@ -73,9 +73,9 @@ extern void chm_voice(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, const char **parv, int *errors, int dir, char c, long mode_type); -extern void construct_noparam_modes(void); -extern void find_orphaned_cflags(void); -extern unsigned int find_cflag_slot(void); +extern unsigned int cflag_add(char c, ChannelModeFunc function); +extern void cflag_orphan(char c); +extern void construct_cflags_strings(void); extern char cflagsbuf[256]; extern char cflagsmyinfo[256]; diff --git a/src/chmode.c b/src/chmode.c index d4e284c47..ea0613ba5 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -72,12 +72,11 @@ int chmode_flags[256]; /* OPTIMIZE ME! -- dwr */ void -construct_noparam_modes(void) +construct_cflags_strings(void) { int i; char *ptr = cflagsbuf; char *ptr2 = cflagsmyinfo; - static int prev_chmode_flags[256]; *ptr = '\0'; *ptr2 = '\0'; @@ -99,22 +98,6 @@ construct_noparam_modes(void) chmode_flags[i] = 0; } - if (prev_chmode_flags[i] != 0 && prev_chmode_flags[i] != chmode_flags[i]) - { - if (chmode_flags[i] == 0) - { - chmode_table[i].set_func = chm_orphaned; - sendto_realops_snomask(SNO_DEBUG, L_ALL, "Cmode +%c is now orphaned", i); - } - else - { - sendto_realops_snomask(SNO_DEBUG, L_ALL, "Orphaned cmode +%c is picked up by module", i); - } - chmode_flags[i] = prev_chmode_flags[i]; - } - else - prev_chmode_flags[i] = chmode_flags[i]; - switch (chmode_flags[i]) { case MODE_EXLIMIT: @@ -158,7 +141,7 @@ construct_noparam_modes(void) * 0 if no cflags are available * side effects - NONE */ -unsigned int +static unsigned int find_cflag_slot(void) { unsigned int all_cflags = 0, my_cflag = 0, i; @@ -172,6 +155,34 @@ find_cflag_slot(void) return my_cflag; } +unsigned int +cflag_add(char c_, ChannelModeFunc function) +{ + int c = (unsigned char)c_; + + if (chmode_table[c].set_func != chm_nosuch && + chmode_table[c].set_func != chm_orphaned) + return 0; + + if (chmode_table[c].set_func == chm_nosuch) + chmode_table[c].mode_type = find_cflag_slot(); + if (chmode_table[c].mode_type == 0) + return 0; + chmode_table[c].set_func = function; + construct_cflags_strings(); + return chmode_table[c].mode_type; +} + +void +cflag_orphan(char c_) +{ + int c = (unsigned char)c_; + + s_assert(chmode_flags[c] != 0); + chmode_table[c].set_func = chm_orphaned; + construct_cflags_strings(); +} + static int get_channel_access(struct Client *source_p, struct membership *msptr) { diff --git a/src/ircd.c b/src/ircd.c index 8577081bf..a9f6cfbd1 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -649,13 +649,7 @@ main(int argc, char *argv[]) init_monitor(); init_isupport(); - /* noparam core modes have to be initialized before the module - * system is initialized, otherwise we have a table collision. - * - * modules call this after they are done initializing... - * --nenolod - */ - construct_noparam_modes(); + construct_cflags_strings(); load_all_modules(1); #ifndef STATIC_MODULES From 0ffb810660845caa183339cc48ffa304dd50c887 Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Mon, 5 Apr 2010 15:28:44 -0400 Subject: [PATCH 12/13] Add a configuration option for ident_timeout. --- doc/example.conf | 1 + doc/reference.conf | 5 +++++ include/s_conf.h | 1 + modules/m_info.c | 6 ++++++ src/ircd.c | 5 ++++- src/newconf.c | 1 + src/s_conf.c | 1 + 7 files changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/example.conf b/doc/example.conf index 4848ed04f..ca0d9abf5 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -475,6 +475,7 @@ general { short_motd = no; ping_cookie = no; connect_timeout = 30 seconds; + ident_timeout = 5; disable_auth = no; no_oper_flood = yes; max_targets = 4; diff --git a/doc/reference.conf b/doc/reference.conf index d71cd0b00..69afcacde 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -1116,6 +1116,11 @@ general { */ connect_timeout = 30 seconds; + /* ident timeout: Amount of time (in seconds) that the IRCd will + * wait for a user to respond to an ident request. + */ + ident_timeout = 5; + /* disable auth: disables identd checking */ disable_auth = no; diff --git a/include/s_conf.h b/include/s_conf.h index b1124f0b9..d1736a479 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -206,6 +206,7 @@ struct config_file_entry int min_nonwildcard_simple; int default_floodcount; int client_flood; + int ident_timeout; int use_egd; int ping_cookie; int tkline_expire_notices; diff --git a/modules/m_info.c b/modules/m_info.c index 3cdd7ba43..6569dc842 100644 --- a/modules/m_info.c +++ b/modules/m_info.c @@ -133,6 +133,12 @@ static struct InfoStruct info_table[] = { &ConfigFileEntry.connect_timeout, "Connect timeout for connections to servers" }, + { + "ident_timeout", + OUTPUT_DECIMAL, + &ConfigFileEntry.ident_timeout, + "Amount of time the server waits for ident responses from clients", + }, { "default_floodcount", OUTPUT_DECIMAL, diff --git a/src/ircd.c b/src/ircd.c index a9f6cfbd1..add5f65b8 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -324,7 +324,10 @@ initialize_global_set_options(void) splitchecking = 1; } - GlobalSetOptions.ident_timeout = IDENT_TIMEOUT; + if(ConfigFileEntry.ident_timeout) + GlobalSetOptions.ident_timeout = ConfigFileEntry.ident_timeout; + else + GlobalSetOptions.ident_timeout = IDENT_TIMEOUT; rb_strlcpy(GlobalSetOptions.operstring, ConfigFileEntry.default_operstring, diff --git a/src/newconf.c b/src/newconf.c index 307d08905..b02beece2 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -2136,6 +2136,7 @@ static struct ConfEntry conf_general_table[] = { "collision_fnc", CF_YESNO, NULL, 0, &ConfigFileEntry.collision_fnc }, { "connect_timeout", CF_TIME, NULL, 0, &ConfigFileEntry.connect_timeout }, { "default_floodcount", CF_INT, NULL, 0, &ConfigFileEntry.default_floodcount }, + { "ident_timeout", CF_INT, NULL, 0, &ConfigFileEntry.ident_timeout }, { "disable_auth", CF_YESNO, NULL, 0, &ConfigFileEntry.disable_auth }, { "dots_in_ident", CF_INT, NULL, 0, &ConfigFileEntry.dots_in_ident }, { "failed_oper_notice", CF_YESNO, NULL, 0, &ConfigFileEntry.failed_oper_notice }, diff --git a/src/s_conf.c b/src/s_conf.c index dc733430f..1bc1bda2d 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -782,6 +782,7 @@ set_default_conf(void) ConfigFileEntry.min_nonwildcard = 4; ConfigFileEntry.min_nonwildcard_simple = 3; ConfigFileEntry.default_floodcount = 8; + ConfigFileEntry.ident_timeout = 5; ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT; ConfigFileEntry.tkline_expire_notices = 0; From 944b0584ea02fd67ae77a36aef4f8600ba58d73d Mon Sep 17 00:00:00 2001 From: JD Horelick Date: Mon, 5 Apr 2010 16:29:11 -0400 Subject: [PATCH 13/13] Change config option for ident_timeout to default_ident_timeout as jilles recommended. --- doc/example.conf | 2 +- doc/reference.conf | 2 +- include/s_conf.h | 2 +- modules/m_info.c | 4 ++-- src/ircd.c | 4 ++-- src/newconf.c | 2 +- src/s_conf.c | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/example.conf b/doc/example.conf index ca0d9abf5..8c9dbf230 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -475,7 +475,7 @@ general { short_motd = no; ping_cookie = no; connect_timeout = 30 seconds; - ident_timeout = 5; + default_ident_timeout = 5; disable_auth = no; no_oper_flood = yes; max_targets = 4; diff --git a/doc/reference.conf b/doc/reference.conf index 69afcacde..4c0e604ba 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -1119,7 +1119,7 @@ general { /* ident timeout: Amount of time (in seconds) that the IRCd will * wait for a user to respond to an ident request. */ - ident_timeout = 5; + default_ident_timeout = 5; /* disable auth: disables identd checking */ disable_auth = no; diff --git a/include/s_conf.h b/include/s_conf.h index d1736a479..03e0d5faf 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -206,7 +206,7 @@ struct config_file_entry int min_nonwildcard_simple; int default_floodcount; int client_flood; - int ident_timeout; + int default_ident_timeout; int use_egd; int ping_cookie; int tkline_expire_notices; diff --git a/modules/m_info.c b/modules/m_info.c index 6569dc842..62d75f759 100644 --- a/modules/m_info.c +++ b/modules/m_info.c @@ -134,9 +134,9 @@ static struct InfoStruct info_table[] = { "Connect timeout for connections to servers" }, { - "ident_timeout", + "default_ident_timeout", OUTPUT_DECIMAL, - &ConfigFileEntry.ident_timeout, + &ConfigFileEntry.default_ident_timeout, "Amount of time the server waits for ident responses from clients", }, { diff --git a/src/ircd.c b/src/ircd.c index add5f65b8..b5f8076ac 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -324,8 +324,8 @@ initialize_global_set_options(void) splitchecking = 1; } - if(ConfigFileEntry.ident_timeout) - GlobalSetOptions.ident_timeout = ConfigFileEntry.ident_timeout; + if(ConfigFileEntry.default_ident_timeout) + GlobalSetOptions.ident_timeout = ConfigFileEntry.default_ident_timeout; else GlobalSetOptions.ident_timeout = IDENT_TIMEOUT; diff --git a/src/newconf.c b/src/newconf.c index b02beece2..1769d35d8 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -2136,7 +2136,7 @@ static struct ConfEntry conf_general_table[] = { "collision_fnc", CF_YESNO, NULL, 0, &ConfigFileEntry.collision_fnc }, { "connect_timeout", CF_TIME, NULL, 0, &ConfigFileEntry.connect_timeout }, { "default_floodcount", CF_INT, NULL, 0, &ConfigFileEntry.default_floodcount }, - { "ident_timeout", CF_INT, NULL, 0, &ConfigFileEntry.ident_timeout }, + { "default_ident_timeout", CF_INT, NULL, 0, &ConfigFileEntry.default_ident_timeout }, { "disable_auth", CF_YESNO, NULL, 0, &ConfigFileEntry.disable_auth }, { "dots_in_ident", CF_INT, NULL, 0, &ConfigFileEntry.dots_in_ident }, { "failed_oper_notice", CF_YESNO, NULL, 0, &ConfigFileEntry.failed_oper_notice }, diff --git a/src/s_conf.c b/src/s_conf.c index 1bc1bda2d..d8808c70a 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -782,7 +782,7 @@ set_default_conf(void) ConfigFileEntry.min_nonwildcard = 4; ConfigFileEntry.min_nonwildcard_simple = 3; ConfigFileEntry.default_floodcount = 8; - ConfigFileEntry.ident_timeout = 5; + ConfigFileEntry.default_ident_timeout = 5; ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT; ConfigFileEntry.tkline_expire_notices = 0;