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 6a79129e..4848ed04 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 10971d4d..ce283109 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 4cacc5e0..03d78a66 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 d3ddb3b8..3cdd7ba4 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 46ff7304..364c30b0 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 24749a83..307d0890 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 946380db..11d2d0a1 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 94aebaca..6e06ef73 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 ce283109..6074ed0f 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 5d25900d..f20ad564 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 03d78a66..b1124f0b 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 f61ba076..0efe6ef3 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 364c30b0..d6e22bc5 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 556ad005..566a3692 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 11d2d0a1..cfd6048d 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 0efe6ef3..1fecd3f1 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 566a3692..315a686f 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 315a686f..d1975ecd 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 6074ed0f..d71cd0b0 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 f20ad564..fb7bb347 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 090f7659..466e94a1 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 1fecd3f1..8481282d 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 01b41b79..cdcaecbb 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 7483b6e5..1a159f14 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 cdcaecbb..af727478 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 8481282d..d966edd4 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 d6e22bc5..89ba2353 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 cfd6048d..dc733430 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 673c1762..56171ec4 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 00000000..96abca29 --- /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 9380c3df..c478e91e 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 4912e5a7..5cb87ab3 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 197aac69..2808bb18 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 466e94a1..923871ed 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 a9c04a64..f30c9bf3 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 d4e284c4..ea0613ba 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 8577081b..a9f6cfbd 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 4848ed04..ca0d9abf 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 d71cd0b0..69afcacd 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 b1124f0b..d1736a47 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 3cdd7ba4..6569dc84 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 a9f6cfbd..add5f65b 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 307d0890..b02beece 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 dc733430..1bc1bda2 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 ca0d9abf..8c9dbf23 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 69afcacd..4c0e604b 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 d1736a47..03e0d5fa 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 6569dc84..62d75f75 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 add5f65b..b5f8076a 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 b02beece..1769d35d 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 1bc1bda2..d8808c70 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;