diff options
Diffstat (limited to 'modules/m_info.c')
-rw-r--r-- | modules/m_info.c | 733 |
1 files changed, 733 insertions, 0 deletions
diff --git a/modules/m_info.c b/modules/m_info.c new file mode 100644 index 0000000..c3e81d7 --- /dev/null +++ b/modules/m_info.c @@ -0,0 +1,733 @@ +/* + * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd). + * m_info.c: Sends information about the server. + * + * Copyright (C) 2005 by the past and present ircd coders, and others. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * $Id$ + */ + +#include "stdinc.h" +#include "list.h" +#include "channel.h" +#include "client.h" +#include "irc_string.h" +#include "ircd.h" +#include "numeric.h" +#include "s_serv.h" +#include "s_user.h" +#include "send.h" +#include "conf.h" +#include "parse.h" +#include "modules.h" + + +static void send_conf_options(struct Client *); +static void send_birthdate_online_time(struct Client *); +static void send_info_text(struct Client *); + +/* + * jdc -- Structure for our configuration value table + */ +struct InfoStruct +{ + const char *name; /* Displayed variable name */ + unsigned int output_type; /* See below #defines */ + void *option; /* Pointer reference to the value */ + const char *desc; /* ASCII description of the variable */ +}; + +/* Types for output_type in InfoStruct */ +#define OUTPUT_STRING 0x0001 /* Output option as %s w/ dereference */ +#define OUTPUT_STRING_PTR 0x0002 /* Output option as %s w/out deference */ +#define OUTPUT_DECIMAL 0x0004 /* Output option as decimal (%d) */ +#define OUTPUT_BOOLEAN 0x0008 /* Output option as "ON" or "OFF" */ +#define OUTPUT_BOOLEAN_YN 0x0010 /* Output option as "YES" or "NO" */ +#define OUTPUT_BOOLEAN2 0x0020 /* Output option as "YES/NO/MASKED" */ + +static const struct InfoStruct info_table[] = +{ + /* --[ START OF TABLE ]-------------------------------------------- */ + + { + "CPATH", + OUTPUT_STRING, + &ConfigFileEntry.configfile, + "Path to Main Configuration File" + }, + { + "DPATH", + OUTPUT_STRING, + &ConfigFileEntry.dpath, + "Directory Containing Configuration Files" + }, + { + "DLPATH", + OUTPUT_STRING, + &ConfigFileEntry.dlinefile, + "Path to D-line File" + }, + { + "KPATH", + OUTPUT_STRING, + &ConfigFileEntry.klinefile, + "Path to K-line File" + }, + { + "network_name", + OUTPUT_STRING, + &ServerInfo.network_name, + "Network name" + }, + { + "network_desc", + OUTPUT_STRING, + &ServerInfo.network_desc, + "Network description" + }, + { + "hub", + OUTPUT_BOOLEAN_YN, + &ServerInfo.hub, + "Server is a hub" + }, + { + "use_logging", + OUTPUT_BOOLEAN_YN, + &ConfigLoggingEntry.use_logging, + "Enable logging" + }, + { + "restrict_channels", + OUTPUT_BOOLEAN_YN, + &ConfigChannel.restrict_channels, + "Only reserved channels are allowed" + }, + { + "knock_delay", + OUTPUT_DECIMAL, + &ConfigChannel.knock_delay, + "Delay between a users KNOCK attempts" + }, + { + "knock_delay_channel", + OUTPUT_DECIMAL, + &ConfigChannel.knock_delay_channel, + "Delay between KNOCK attempts to a channel" + }, + { + "max_chans_per_user", + OUTPUT_DECIMAL, + &ConfigChannel.max_chans_per_user, + "Maximum number of channels a user can join" + }, + { + "max_chans_per_oper", + OUTPUT_DECIMAL, + &ConfigChannel.max_chans_per_oper, + "Maximum number of channels an oper can join" + }, + { + "quiet_on_ban", + OUTPUT_BOOLEAN_YN, + &ConfigChannel.quiet_on_ban, + "Banned users may not send text to a channel" + }, + { + "max_bans", + OUTPUT_DECIMAL, + &ConfigChannel.max_bans, + "Total +b/e/I modes allowed in a channel" + }, + { + "default_split_user_count", + OUTPUT_DECIMAL, + &ConfigChannel.default_split_user_count, + "Startup value of SPLITUSERS" + }, + { + "default_split_server_count", + OUTPUT_DECIMAL, + &ConfigChannel.default_split_server_count, + "Startup value of SPLITNUM" + }, + { + "no_create_on_split", + OUTPUT_BOOLEAN_YN, + &ConfigChannel.no_create_on_split, + "Disallow creation of channels when split" + }, + { + "no_join_on_split", + OUTPUT_BOOLEAN_YN, + &ConfigChannel.no_join_on_split, + "Disallow joining channels when split" + }, + { + "flatten_links", + OUTPUT_BOOLEAN_YN, + &ConfigServerHide.flatten_links, + "Flatten /links list" + }, + { + "links_delay", + OUTPUT_DECIMAL, + &ConfigServerHide.links_delay, + "Links rehash delay" + }, + { + "hidden", + OUTPUT_BOOLEAN_YN, + &ConfigServerHide.hidden, + "Hide this server from a flattened /links on remote servers" + }, + { + "hide_servers", + OUTPUT_BOOLEAN_YN, + &ConfigServerHide.hide_servers, + "Hide servernames from users" + }, + { + "hidden_name", + OUTPUT_STRING, + &ConfigServerHide.hidden_name, + "Server name users see if hide_servers = yes" + }, + { + "hide_server_ips", + OUTPUT_BOOLEAN_YN, + &ConfigServerHide.hide_server_ips, + "Prevent people from seeing server IPs" + }, + { + "gline_min_cidr", + OUTPUT_DECIMAL, + &ConfigFileEntry.gline_min_cidr, + "Minimum required length of a CIDR bitmask for IPv4 G-Lines" + }, + { + "gline_min_cidr6", + OUTPUT_DECIMAL, + &ConfigFileEntry.gline_min_cidr6, + "Minimum required length of a CIDR bitmask for IPv6 G-Lines" + }, + { + "invisible_on_connect", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.invisible_on_connect, + "Automatically set mode +i on connecting users" + }, + { + "kill_chase_time_limit", + OUTPUT_DECIMAL, + &ConfigFileEntry.kill_chase_time_limit, + "Nick Change Tracker for KILL" + }, + { + "hide_spoof_ips", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.hide_spoof_ips, + "Hide spoofed IP's" + }, + { + "ignore_bogus_ts", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.ignore_bogus_ts, + "Ignore bogus timestamps from other servers" + }, + { + "disable_auth", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.disable_auth, + "Completely disable ident lookups" + }, + { + "disable_remote_commands", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.disable_remote, + "Prevent users issuing commands on remote servers" + }, + { + "tkline_expire_notices", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.tkline_expire_notices, + "Show temporary kline/xline expire notices" + }, + { + "default_floodcount", + OUTPUT_DECIMAL, + &ConfigFileEntry.default_floodcount, + "Startup value of FLOODCOUNT" + }, + { + "failed_oper_notice", + OUTPUT_BOOLEAN, + &ConfigFileEntry.failed_oper_notice, + "Inform opers if someone /oper's with the wrong password" + }, + { + "dots_in_ident", + OUTPUT_DECIMAL, + &ConfigFileEntry.dots_in_ident, + "Number of permissable dots in an ident" + }, + { + "min_nonwildcard", + OUTPUT_DECIMAL, + &ConfigFileEntry.min_nonwildcard, + "Minimum non-wildcard chars in K/G lines" + }, + { + "min_nonwildcard_simple", + OUTPUT_DECIMAL, + &ConfigFileEntry.min_nonwildcard_simple, + "Minimum non-wildcards in gecos bans" + }, + { + "max_accept", + OUTPUT_DECIMAL, + &ConfigFileEntry.max_accept, + "Maximum nicknames on accept list" + }, + { + "anti_nick_flood", + OUTPUT_BOOLEAN, + &ConfigFileEntry.anti_nick_flood, + "NICK flood protection" + }, + { + "max_nick_time", + OUTPUT_DECIMAL, + &ConfigFileEntry.max_nick_time, + "NICK flood protection time interval" + }, + { + "max_nick_changes", + OUTPUT_DECIMAL, + &ConfigFileEntry.max_nick_changes, + "NICK change threshhold setting" + }, + { + "anti_spam_exit_message_time", + OUTPUT_DECIMAL, + &ConfigFileEntry.anti_spam_exit_message_time, + "Duration a client must be connected for to have an exit message" + }, + { + "ts_warn_delta", + OUTPUT_DECIMAL, + &ConfigFileEntry.ts_warn_delta, + "Maximum permitted TS delta before displaying a warning" + }, + { + "ts_max_delta", + OUTPUT_DECIMAL, + &ConfigFileEntry.ts_max_delta, + "Maximum permitted TS delta from another server" + }, + { + "warn_no_nline", + OUTPUT_BOOLEAN, + &ConfigFileEntry.warn_no_nline, + "Display warning if connecting server lacks N-line" + }, + { + "stats_o_oper_only", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.stats_o_oper_only, + "STATS O output is only shown to operators" + }, + { + "stats_P_oper_only", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.stats_P_oper_only, + "STATS P is only shown to operators" + }, + { + "stats_i_oper_only", + OUTPUT_BOOLEAN2, + &ConfigFileEntry.stats_i_oper_only, + "STATS I output is only shown to operators" + }, + { + "stats_k_oper_only", + OUTPUT_BOOLEAN2, + &ConfigFileEntry.stats_k_oper_only, + "STATS K output is only shown to operators" + }, + { + "caller_id_wait", + OUTPUT_DECIMAL, + &ConfigFileEntry.caller_id_wait, + "Minimum delay between notifying UMODE +g users of messages" + }, + { + "opers_bypass_callerid", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.opers_bypass_callerid, + "Allows IRC operators to message users who are +g (callerid)" + }, + { + "pace_wait_simple", + OUTPUT_DECIMAL, + &ConfigFileEntry.pace_wait_simple, + "Minimum delay between less intensive commands" + }, + { + "pace_wait", + OUTPUT_DECIMAL, + &ConfigFileEntry.pace_wait, + "Minimum delay between uses of certain commands" + }, + { + "short_motd", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.short_motd, + "Do not show MOTD; only tell clients they should read it" + }, + { + "ping_cookie", + OUTPUT_BOOLEAN, + &ConfigFileEntry.ping_cookie, + "Require ping cookies to connect" + }, + { + "no_oper_flood", + OUTPUT_BOOLEAN, + &ConfigFileEntry.no_oper_flood, + "Reduce flood control for operators" + }, + { + "true_no_oper_flood", + OUTPUT_BOOLEAN, + &ConfigFileEntry.true_no_oper_flood, + "Completely disable flood control for operators" + }, + { + "oper_pass_resv", + OUTPUT_BOOLEAN_YN, + &ConfigFileEntry.oper_pass_resv, + "Opers can over-ride RESVs" + }, + { + "max_targets", + OUTPUT_DECIMAL, + &ConfigFileEntry.max_targets, + "The maximum number of PRIVMSG/NOTICE targets" + }, + { + "throttle_time", + OUTPUT_DECIMAL, + &ConfigFileEntry.throttle_time, + "Minimum time between client reconnects" + }, + { + "glines", + OUTPUT_BOOLEAN, + &ConfigFileEntry.glines, + "G-line (network-wide K-line) support" + }, + { + "gline_duration", + OUTPUT_DECIMAL, + &ConfigFileEntry.gline_time, + "Expiry time for G-lines" + }, + + { + "gline_request_duration", + OUTPUT_DECIMAL, + &ConfigFileEntry.gline_request_time, + "Expiry time for pending G-lines" + }, + + /* --[ END OF TABLE ]---------------------------------------------- */ + { + NULL, + 0, + NULL, + 0 + } +}; + +/* +** m_info() +** parv[0] = sender prefix +** parv[1] = servername +*/ +static void +m_info(struct Client *client_p, struct Client *source_p, + int parc, char *parv[]) +{ + static time_t last_used = 0; + + if ((last_used + ConfigFileEntry.pace_wait) > CurrentTime) + { + /* safe enough to give this on a local connect only */ + sendto_one(source_p, form_str(RPL_LOAD2HI), + me.name, source_p->name); + return; + } + + last_used = CurrentTime; + + if (!ConfigFileEntry.disable_remote) + if (hunt_server(client_p,source_p, ":%s INFO :%s", 1, + parc, parv) != HUNTED_ISME) + return; + + send_info_text(source_p); +} + +/* +** mo_info() +** parv[0] = sender prefix +** parv[1] = servername +*/ +static void +mo_info(struct Client *client_p, struct Client *source_p, + int parc, char *parv[]) +{ + if (hunt_server(client_p, source_p, ":%s INFO :%s", 1, + parc, parv) != HUNTED_ISME) + return; + + send_info_text(source_p); +} + +/* +** ms_info() +** parv[0] = sender prefix +** parv[1] = servername +*/ +static void +ms_info(struct Client *client_p, struct Client *source_p, + int parc, char *parv[]) +{ + if (!IsClient(source_p)) + return; + + if (hunt_server(client_p, source_p, ":%s INFO :%s", 1, + parc, parv) != HUNTED_ISME) + return; + + send_info_text(source_p); +} + +/* send_info_text() + * + * inputs - client pointer to send info text to + * output - NONE + * side effects - info text is sent to client + */ +static void +send_info_text(struct Client *source_p) +{ + const char **text = infotext; + char *source, *target; + + sendto_realops_flags(UMODE_SPY, L_ALL, + "INFO requested by %s (%s@%s) [%s]", + source_p->name, source_p->username, + source_p->host, source_p->servptr->name); + + if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && + HasID(source_p)) + source = me.id, target = source_p->id; + else + source = me.name, target = source_p->name; + + while (*text) + { + const char *line = *text++; + + if (*line == '\0') + line = " "; + + sendto_one(source_p, form_str(RPL_INFO), + source, target, line); + } + + if (HasUMode(source_p, UMODE_OPER)) + send_conf_options(source_p); + + send_birthdate_online_time(source_p); + + sendto_one(source_p, form_str(RPL_ENDOFINFO), + me.name, source_p->name); +} + +/* send_birthdate_online_time() + * + * inputs - client pointer to send to + * output - NONE + * side effects - birthdate and online time are sent + */ +static void +send_birthdate_online_time(struct Client *source_p) +{ + if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p)) + { + sendto_one(source_p, ":%s %d %s :On-line since %s", + me.id, RPL_INFO, source_p->id, + myctime(me.localClient->firsttime)); + } + else + { + sendto_one(source_p, ":%s %d %s :On-line since %s", + me.name, RPL_INFO, source_p->name, + myctime(me.localClient->firsttime)); + } +} + +/* send_conf_options() + * + * inputs - client pointer to send to + * output - NONE + * side effects - send config options to client + */ +static void +send_conf_options(struct Client *source_p) +{ + const char *from, *to; + const struct InfoStruct *iptr = NULL; + + /* Now send them a list of all our configuration options + * (mostly from defaults.h and config.h) + */ + if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p)) + { + from = me.id; + to = source_p->id; + } + else + { + from = me.name; + to = source_p->name; + } + + /* + * Parse the info_table[] and do the magic. + */ + for (iptr = info_table; iptr->name; ++iptr) + { + switch (iptr->output_type) + { + /* For "char *" references */ + case OUTPUT_STRING: + { + const char *option = *((char **)iptr->option); + + sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", + from, RPL_INFO, to, + iptr->name, option ? option : "NONE", + iptr->desc ? iptr->desc : "<none>"); + break; + } + + /* For "char foo[]" references */ + case OUTPUT_STRING_PTR: + { + const char *option = iptr->option; + + sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", + from, RPL_INFO, to, + iptr->name, option ? option : "NONE", + iptr->desc ? iptr->desc : "<none>"); + break; + } + + /* Output info_table[i].option as a decimal value. */ + case OUTPUT_DECIMAL: + { + const int option = *((int *)iptr->option); + + sendto_one(source_p, ":%s %d %s :%-30s %-5d [%-30s]", + from, RPL_INFO, to, iptr->name, + option, iptr->desc ? iptr->desc : "<none>"); + break; + } + + /* Output info_table[i].option as "ON" or "OFF" */ + case OUTPUT_BOOLEAN: + { + const int option = *((int *)iptr->option); + + sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", + from, RPL_INFO, to, + iptr->name, option ? "ON" : "OFF", + iptr->desc ? iptr->desc : "<none>"); + + break; + } + + /* Output info_table[i].option as "YES" or "NO" */ + case OUTPUT_BOOLEAN_YN: + { + int option = *((int *)iptr->option); + + sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", + from, RPL_INFO, to, + iptr->name, option ? "YES" : "NO", + iptr->desc ? iptr->desc : "<none>"); + break; + } + + case OUTPUT_BOOLEAN2: + { + int option = *((int *)iptr->option); + + sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]", + from, RPL_INFO, to, + iptr->name, option ? ((option == 1) ? "MASK" : "YES") : "NO", + iptr->desc ? iptr->desc : "<none>"); + break; + } + } + } + + sendto_one(source_p, form_str(RPL_INFO), + from, to, ""); +} + +static struct Message info_msgtab = { + "INFO", 0, 0, 0, MAXPARA, MFLG_SLOW, 0, + { m_unregistered, m_info, ms_info, m_ignore, mo_info, m_ignore } +}; + +static void +module_init(void) +{ + mod_add_cmd(&info_msgtab); +} + +static void +module_exit(void) +{ + mod_del_cmd(&info_msgtab); +} + +struct module module_entry = { + .node = { NULL, NULL, NULL }, + .name = NULL, + .version = "$Revision$", + .handle = NULL, + .modinit = module_init, + .modexit = module_exit, + .flags = 0 +}; |