X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/b2f0da886e87529bd835e30da680d5c4284367ef..55abcbb20aeabcf2e878a9c65c9697210dd10079:/modules/m_stats.c diff --git a/modules/m_stats.c b/modules/m_stats.c index f7c2c936..f61e4885 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -25,32 +25,29 @@ */ #include "stdinc.h" -#include "tools.h" /* rb_dlink_node/rb_dlink_list */ #include "class.h" /* report_classes */ #include "client.h" /* Client */ #include "common.h" /* TRUE/FALSE */ -#include "irc_string.h" +#include "match.h" #include "ircd.h" /* me */ #include "listener.h" /* show_ports */ -#include "s_gline.h" #include "msg.h" /* Message */ #include "hostmask.h" /* report_mtrie_conf_links */ #include "numeric.h" /* ERR_xxx */ #include "scache.h" /* list_scache */ #include "send.h" /* sendto_one */ -#include "commio.h" /* highest_fd */ #include "s_conf.h" /* ConfItem */ #include "s_serv.h" /* hunt_server */ -#include "s_stats.h" /* tstats */ +#include "s_stats.h" #include "s_user.h" /* show_opers */ -#include "event.h" /* events */ #include "blacklist.h" /* dnsbl stuff */ -#include "linebuf.h" #include "parse.h" #include "modules.h" #include "hook.h" #include "s_newconf.h" #include "hash.h" +#include "reject.h" +#include "whowas.h" static int m_stats (struct Client *, struct Client *, int, const char **); @@ -73,7 +70,8 @@ DECLARE_MODULE_AV1(stats, NULL, NULL, stats_clist, stats_hlist, NULL, "$Revision const char *Lformat = "%s %u %u %u %u %u :%u %u %s"; -static void stats_l_list(struct Client *s, const char *, int, int, rb_dlink_list *, char); +static void stats_l_list(struct Client *s, const char *, int, int, rb_dlink_list *, char, + int (*check_fn)(struct Client *target_p)); static void stats_l_client(struct Client *source_p, struct Client *target_p, char statchar); @@ -84,12 +82,12 @@ static void stats_p_spy(struct Client *); struct StatsStruct { char letter; - void (*handler) (); + void (*handler) (struct Client *source_p); int need_oper; int need_admin; }; -static void stats_dns_servers (struct Client *); +static void stats_dns_servers(struct Client *); static void stats_delay(struct Client *); static void stats_hash(struct Client *); static void stats_connect(struct Client *); @@ -97,8 +95,7 @@ static void stats_tdeny(struct Client *); static void stats_deny(struct Client *); static void stats_exempt(struct Client *); static void stats_events(struct Client *); -static void stats_glines(struct Client *); -static void stats_pending_glines(struct Client *); +static void stats_prop_klines(struct Client *); static void stats_hubleaf(struct Client *); static void stats_auth(struct Client *); static void stats_tklines(struct Client *); @@ -106,6 +103,7 @@ static void stats_klines(struct Client *); static void stats_messages(struct Client *); static void stats_dnsbl(struct Client *); static void stats_oper(struct Client *); +static void stats_privset(struct Client *); static void stats_operedup(struct Client *); static void stats_ports(struct Client *); static void stats_tresv(struct Client *); @@ -122,6 +120,8 @@ static void stats_memory(struct Client *); static void stats_servlinks(struct Client *); static void stats_ltrace(struct Client *, int, const char **); static void stats_ziplinks(struct Client *); +static void stats_comm(struct Client *); +static void stats_capability(struct Client *); /* This table contains the possible stats items, in order: * stats letter, function to call, operonly? adminonly? @@ -134,28 +134,27 @@ static struct StatsStruct stats_cmd_table[] = { {'b', stats_delay, 1, 1, }, {'B', stats_hash, 1, 1, }, {'c', stats_connect, 0, 0, }, - {'C', stats_connect, 0, 0, }, + {'C', stats_capability, 1, 0, }, {'d', stats_tdeny, 1, 0, }, {'D', stats_deny, 1, 0, }, {'e', stats_exempt, 1, 0, }, {'E', stats_events, 1, 1, }, - {'f', rb_dump, 1, 1, }, - {'F', rb_dump, 1, 1, }, - {'g', stats_pending_glines, 1, 0, }, - {'G', stats_glines, 1, 0, }, + {'f', stats_comm, 1, 1, }, + {'F', stats_comm, 1, 1, }, + {'g', stats_prop_klines, 1, 0, }, {'h', stats_hubleaf, 0, 0, }, {'H', stats_hubleaf, 0, 0, }, {'i', stats_auth, 0, 0, }, {'I', stats_auth, 0, 0, }, {'k', stats_tklines, 0, 0, }, {'K', stats_klines, 0, 0, }, - {'l', stats_ltrace, 0, 0, }, - {'L', stats_ltrace, 0, 0, }, + {'l', NULL /* special */, 0, 0, }, + {'L', NULL /* special */, 0, 0, }, {'m', stats_messages, 0, 0, }, {'M', stats_messages, 0, 0, }, {'n', stats_dnsbl, 0, 0, }, {'o', stats_oper, 0, 0, }, - {'O', stats_oper, 0, 0, }, + {'O', stats_privset, 1, 0, }, {'p', stats_operedup, 0, 0, }, {'P', stats_ports, 0, 0, }, {'q', stats_tresv, 1, 0, }, @@ -180,12 +179,11 @@ static struct StatsStruct stats_cmd_table[] = { /* * m_stats by fl_ - * parv[0] = sender prefix * parv[1] = stat letter/command * parv[2] = (if present) server/mask in stats L, or target * * This will search the tables for the appropriate stats letter, - * if found execute it. + * if found execute it. */ static int m_stats(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) @@ -199,17 +197,17 @@ m_stats(struct Client *client_p, struct Client *source_p, int parc, const char * if(MyClient(source_p) && !IsOper(source_p)) { /* Check the user is actually allowed to do /stats, and isnt flooding */ - if((last_used + ConfigFileEntry.pace_wait) > CurrentTime) + if((last_used + ConfigFileEntry.pace_wait) > rb_current_time()) { /* safe enough to give this on a local connect only */ sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, source_p->name, "STATS"); - sendto_one_numeric(source_p, RPL_ENDOFSTATS, + sendto_one_numeric(source_p, RPL_ENDOFSTATS, form_str(RPL_ENDOFSTATS), statchar); return 0; } else - last_used = CurrentTime; + last_used = rb_current_time(); } if(hunt_server (client_p, source_p, ":%s STATS %s :%s", 2, parc, parv) != HUNTED_ISME) @@ -218,7 +216,7 @@ m_stats(struct Client *client_p, struct Client *source_p, int parc, const char * if((statchar != 'L') && (statchar != 'l')) stats_spy(source_p, statchar, NULL); - for (i = 0; stats_cmd_table[i].handler; i++) + for (i = 0; stats_cmd_table[i].letter; i++) { if(stats_cmd_table[i].letter == statchar) { @@ -241,14 +239,14 @@ m_stats(struct Client *client_p, struct Client *source_p, int parc, const char * /* Blah, stats L needs the parameters, none of the others do.. */ if(statchar == 'L' || statchar == 'l') - stats_cmd_table[i].handler (source_p, parc, parv); + stats_ltrace (source_p, parc, parv); else stats_cmd_table[i].handler (source_p); } } /* Send the end of stats notice, and the stats_spy */ - sendto_one_numeric(source_p, RPL_ENDOFSTATS, + sendto_one_numeric(source_p, RPL_ENDOFSTATS, form_str(RPL_ENDOFSTATS), statchar); return 0; @@ -287,7 +285,7 @@ stats_connect(struct Client *source_p) char *s; rb_dlink_node *ptr; - if((ConfigFileEntry.stats_c_oper_only || + if((ConfigFileEntry.stats_c_oper_only || (ConfigServerHide.flatten_links && !IsExemptShide(source_p))) && !IsOper(source_p)) { @@ -303,31 +301,28 @@ stats_connect(struct Client *source_p) if(ServerConfIllegal(server_p)) continue; - buf[0] = '\0'; s = buf; if(IsOper(source_p)) { if(ServerConfAutoconn(server_p)) *s++ = 'A'; + if(ServerConfSSL(server_p)) + *s++ = 'S'; if(ServerConfTb(server_p)) *s++ = 'T'; if(ServerConfCompressed(server_p)) *s++ = 'Z'; } - if(!buf[0]) + if(s == buf) *s++ = '*'; *s = '\0'; - sendto_one_numeric(source_p, RPL_STATSCLINE, + sendto_one_numeric(source_p, RPL_STATSCLINE, form_str(RPL_STATSCLINE), -#ifndef HIDE_SERVERS_IPS - server_p->host, -#else - "*@127.0.0.1", -#endif + "*@127.0.0.1", buf, server_p->name, server_p->port, server_p->class_name); } @@ -360,7 +355,7 @@ stats_tdeny (struct Client *source_p) get_printable_kline(source_p, aconf, &host, &pass, &user, &oper_reason); - sendto_one_numeric(source_p, RPL_STATSDLINE, + sendto_one_numeric(source_p, RPL_STATSDLINE, form_str (RPL_STATSDLINE), 'd', host, pass, oper_reason ? "|" : "", @@ -397,7 +392,7 @@ stats_deny (struct Client *source_p) get_printable_kline(source_p, aconf, &host, &pass, &user, &oper_reason); - sendto_one_numeric(source_p, RPL_STATSDLINE, + sendto_one_numeric(source_p, RPL_STATSDLINE, form_str (RPL_STATSDLINE), 'D', host, pass, oper_reason ? "|" : "", @@ -439,7 +434,7 @@ stats_exempt(struct Client *source_p) get_printable_conf (aconf, &name, &host, &pass, &user, &port, &classname); - sendto_one_numeric(source_p, RPL_STATSDLINE, + sendto_one_numeric(source_p, RPL_STATSDLINE, form_str(RPL_STATSDLINE), 'e', host, pass, "", ""); } @@ -448,101 +443,50 @@ stats_exempt(struct Client *source_p) static void -stats_events (struct Client *source_p) +stats_events_cb(char *str, void *ptr) { - show_events (source_p); + sendto_one_numeric(ptr, RPL_STATSDEBUG, "E :%s", str); } -/* stats_pending_glines() - * - * input - client pointer - * output - none - * side effects - client is shown list of pending glines - */ static void -stats_pending_glines (struct Client *source_p) +stats_events (struct Client *source_p) { - if(ConfigFileEntry.glines) - { - rb_dlink_node *pending_node; - struct gline_pending *glp_ptr; - char timebuffer[MAX_DATE_STRING]; - struct tm *tmptr; - - RB_DLINK_FOREACH (pending_node, pending_glines.head) - { - glp_ptr = pending_node->data; - - tmptr = localtime (&glp_ptr->time_request1); - strftime (timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr); - - sendto_one_notice(source_p, - ":1) %s!%s@%s on %s requested gline at %s for %s@%s [%s]", - glp_ptr->oper_nick1, - glp_ptr->oper_user1, glp_ptr->oper_host1, - glp_ptr->oper_server1, timebuffer, - glp_ptr->user, glp_ptr->host, glp_ptr->reason1); - - if(glp_ptr->oper_nick2[0]) - { - tmptr = localtime (&glp_ptr->time_request2); - strftime (timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr); - sendto_one_notice(source_p, - ":2) %s!%s@%s on %s requested gline at %s for %s@%s [%s]", - glp_ptr->oper_nick2, - glp_ptr->oper_user2, glp_ptr->oper_host2, - glp_ptr->oper_server2, timebuffer, - glp_ptr->user, glp_ptr->host, glp_ptr->reason2); - } - } - - if(rb_dlink_list_length (&pending_glines) > 0) - sendto_one_notice(source_p, ":End of Pending G-lines"); - } - else - sendto_one_notice(source_p, ":This server does not support G-Lines"); - + rb_dump_events(stats_events_cb, source_p); } -/* stats_glines() - * - * input - client pointer - * output - none - * side effects - client is shown list of glines - */ static void -stats_glines (struct Client *source_p) +stats_prop_klines(struct Client *source_p) { - if(ConfigFileEntry.glines) + struct ConfItem *aconf; + rb_dlink_node *ptr; + char *user, *host, *pass, *oper_reason; + + RB_DLINK_FOREACH(ptr, prop_bans.head) { - rb_dlink_node *gline_node; - struct ConfItem *kill_ptr; + aconf = ptr->data; - RB_DLINK_FOREACH_PREV (gline_node, glines.tail) - { - kill_ptr = gline_node->data; - - sendto_one_numeric(source_p, RPL_STATSKLINE, - form_str(RPL_STATSKLINE), 'G', - kill_ptr->host ? kill_ptr->host : "*", - kill_ptr->user ? kill_ptr->user : "*", - kill_ptr->passwd ? kill_ptr->passwd : "No Reason", - kill_ptr->spasswd ? "|" : "", - kill_ptr->spasswd ? kill_ptr->spasswd : ""); - } + /* Skip non-klines and deactivated klines. */ + if(aconf->status != CONF_KILL) + continue; + + get_printable_kline(source_p, aconf, &host, &pass, + &user, &oper_reason); + + sendto_one_numeric(source_p, RPL_STATSKLINE, + form_str(RPL_STATSKLINE), + 'g', host, user, pass, + oper_reason ? "|" : "", + oper_reason ? oper_reason : ""); } - else - sendto_one_notice(source_p, ":This server does not support G-Lines"); } - static void stats_hubleaf(struct Client *source_p) { struct remote_conf *hub_p; rb_dlink_node *ptr; - if((ConfigFileEntry.stats_h_oper_only || + if((ConfigFileEntry.stats_h_oper_only || (ConfigServerHide.flatten_links && !IsExemptShide(source_p))) && !IsOper(source_p)) { @@ -579,7 +523,7 @@ stats_auth (struct Client *source_p) else if((ConfigFileEntry.stats_i_oper_only == 1) && !IsOper (source_p)) { struct ConfItem *aconf; - char *name, *host, *pass, *user, *classname; + char *name, *host, *pass = "*", *user, *classname; int port; if(MyConnect (source_p)) @@ -587,18 +531,20 @@ stats_auth (struct Client *source_p) (struct sockaddr *)&source_p->localClient->ip, CONF_CLIENT, source_p->localClient->ip.ss_family, - source_p->username); + source_p->username, NULL); else aconf = find_conf_by_address (source_p->host, NULL, NULL, NULL, CONF_CLIENT, - 0, source_p->username); + 0, source_p->username, NULL); if(aconf == NULL) return; get_printable_conf (aconf, &name, &host, &pass, &user, &port, &classname); + if(!EmptyString(aconf->spasswd)) + pass = aconf->spasswd; sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE), - name, show_iline_prefix(source_p, aconf, user), + name, pass, show_iline_prefix(source_p, aconf, user), host, port, classname); } @@ -627,10 +573,10 @@ stats_tklines(struct Client *source_p) (struct sockaddr *)&source_p->localClient->ip, CONF_KILL, source_p->localClient->ip.ss_family, - source_p->username); + source_p->username, NULL); else aconf = find_conf_by_address (source_p->host, NULL, NULL, NULL, CONF_KILL, - 0, source_p->username); + 0, source_p->username, NULL); if(aconf == NULL) return; @@ -641,7 +587,7 @@ stats_tklines(struct Client *source_p) get_printable_kline(source_p, aconf, &host, &pass, &user, &oper_reason); - sendto_one_numeric(source_p, RPL_STATSKLINE, + sendto_one_numeric(source_p, RPL_STATSKLINE, form_str(RPL_STATSKLINE), aconf->flags & CONF_FLAGS_TEMPORARY ? 'k' : 'K', host, user, pass, oper_reason ? "|" : "", oper_reason ? oper_reason : ""); @@ -660,7 +606,7 @@ stats_tklines(struct Client *source_p) { aconf = ptr->data; - get_printable_kline(source_p, aconf, &host, &pass, + get_printable_kline(source_p, aconf, &host, &pass, &user, &oper_reason); sendto_one_numeric(source_p, RPL_STATSKLINE, @@ -693,10 +639,10 @@ stats_klines(struct Client *source_p) (struct sockaddr *)&source_p->localClient->ip, CONF_KILL, source_p->localClient->ip.ss_family, - source_p->username); + source_p->username, NULL); else aconf = find_conf_by_address (source_p->host, NULL, NULL, NULL, CONF_KILL, - 0, source_p->username); + 0, source_p->username, NULL); if(aconf == NULL) return; @@ -754,14 +700,33 @@ stats_oper(struct Client *source_p) RB_DLINK_FOREACH(ptr, oper_conf_list.head) { oper_p = ptr->data; - - sendto_one_numeric(source_p, RPL_STATSOLINE, + + sendto_one_numeric(source_p, RPL_STATSOLINE, form_str(RPL_STATSOLINE), oper_p->username, oper_p->host, oper_p->name, - IsOper(source_p) ? get_oper_privs(oper_p->flags) : "0", "-1"); + IsOper(source_p) ? oper_p->privset->name : "0", "-1"); } } +static void +stats_capability_walk(const char *line, void *data) +{ + struct Client *client_p = data; + + sendto_one_numeric(client_p, RPL_STATSDEBUG, "C :%s", line); +} + +static void +stats_capability(struct Client *client_p) +{ + capability_index_stats(stats_capability_walk, client_p); +} + +static void +stats_privset(struct Client *source_p) +{ + privilegeset_report(source_p); +} /* stats_operedup() * @@ -790,7 +755,7 @@ stats_operedup (struct Client *source_p) sendto_one_numeric(source_p, RPL_STATSDEBUG, "p :%s (%s@%s)", - target_p->name, target_p->username, + target_p->name, target_p->username, target_p->host); } @@ -821,18 +786,18 @@ stats_tresv(struct Client *source_p) { aconf = ptr->data; if(aconf->hold) - sendto_one_numeric(source_p, RPL_STATSQLINE, + sendto_one_numeric(source_p, RPL_STATSQLINE, form_str(RPL_STATSQLINE), - 'q', aconf->port, aconf->name, aconf->passwd); + 'q', aconf->port, aconf->host, aconf->passwd); } HASH_WALK(i, R_MAX, ptr, resvTable) { aconf = ptr->data; if(aconf->hold) - sendto_one_numeric(source_p, RPL_STATSQLINE, + sendto_one_numeric(source_p, RPL_STATSQLINE, form_str(RPL_STATSQLINE), - 'q', aconf->port, aconf->name, aconf->passwd); + 'q', aconf->port, aconf->host, aconf->passwd); } HASH_WALK_END } @@ -849,18 +814,18 @@ stats_resv(struct Client *source_p) { aconf = ptr->data; if(!aconf->hold) - sendto_one_numeric(source_p, RPL_STATSQLINE, + sendto_one_numeric(source_p, RPL_STATSQLINE, form_str(RPL_STATSQLINE), - 'Q', aconf->port, aconf->name, aconf->passwd); + 'Q', aconf->port, aconf->host, aconf->passwd); } HASH_WALK(i, R_MAX, ptr, resvTable) { aconf = ptr->data; if(!aconf->hold) - sendto_one_numeric(source_p, RPL_STATSQLINE, + sendto_one_numeric(source_p, RPL_STATSQLINE, form_str(RPL_STATSQLINE), - 'Q', aconf->port, aconf->name, aconf->passwd); + 'Q', aconf->port, aconf->host, aconf->passwd); } HASH_WALK_END } @@ -891,20 +856,20 @@ stats_usage (struct Client *source_p) if(0 == secs) secs = 1; - rup = (CurrentTime - startup_time) * hzz; + rup = (rb_current_time() - startup_time) * hzz; if(0 == rup) rup = 1; - + sendto_one_numeric(source_p, RPL_STATSDEBUG, - "R :CPU Secs %d:%d User %d:%d System %d:%d", + "R :CPU Secs %d:%02d User %d:%02d System %d:%02d", (int) (secs / 60), (int) (secs % 60), (int) (rus.ru_utime.tv_sec / 60), (int) (rus.ru_utime.tv_sec % 60), - (int) (rus.ru_stime.tv_sec / 60), + (int) (rus.ru_stime.tv_sec / 60), (int) (rus.ru_stime.tv_sec % 60)); sendto_one_numeric(source_p, RPL_STATSDEBUG, "R :RSS %ld ShMem %ld Data %ld Stack %ld", - rus.ru_maxrss, (rus.ru_ixrss / rup), + rus.ru_maxrss, (rus.ru_ixrss / rup), (rus.ru_idrss / rup), (rus.ru_isrss / rup)); sendto_one_numeric(source_p, RPL_STATSDEBUG, "R :Swaps %d Reclaims %d Faults %d", @@ -917,14 +882,90 @@ stats_usage (struct Client *source_p) (int) rus.ru_msgrcv, (int) rus.ru_msgsnd); sendto_one_numeric(source_p, RPL_STATSDEBUG, "R :Signals %d Context Vol. %d Invol %d", - (int) rus.ru_nsignals, (int) rus.ru_nvcsw, + (int) rus.ru_nsignals, (int) rus.ru_nvcsw, (int) rus.ru_nivcsw); } static void stats_tstats (struct Client *source_p) { - tstats (source_p); + struct Client *target_p; + struct ServerStatistics sp; + rb_dlink_node *ptr; + + memcpy(&sp, &ServerStats, sizeof(struct ServerStatistics)); + + RB_DLINK_FOREACH(ptr, serv_list.head) + { + target_p = ptr->data; + + sp.is_sbs += target_p->localClient->sendB; + sp.is_sbr += target_p->localClient->receiveB; + sp.is_sti += (unsigned long long)(rb_current_time() - target_p->localClient->firsttime); + sp.is_sv++; + } + + RB_DLINK_FOREACH(ptr, lclient_list.head) + { + target_p = ptr->data; + + sp.is_cbs += target_p->localClient->sendB; + sp.is_cbr += target_p->localClient->receiveB; + sp.is_cti += (unsigned long long)(rb_current_time() - target_p->localClient->firsttime); + sp.is_cl++; + } + + RB_DLINK_FOREACH(ptr, unknown_list.head) + { + sp.is_ni++; + } + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :accepts %u refused %u", sp.is_ac, sp.is_ref); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :rejected %u delaying %lu", + sp.is_rej, delay_exit_length()); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :throttled refused %u throttle list size %lu", sp.is_thr, throttle_size()); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :nicks being delayed %lu", + get_nd_count()); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :unknown commands %u prefixes %u", + sp.is_unco, sp.is_unpf); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :nick collisions %u saves %u unknown closes %u", + sp.is_kill, sp.is_save, sp.is_ni); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :wrong direction %u empty %u", + sp.is_wrdi, sp.is_empt); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :numerics seen %u", sp.is_num); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :tgchange blocked msgs %u restricted addrs %lu", + sp.is_tgch, rb_dlink_list_length(&tgchange_list)); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :ratelimit blocked commands %u", sp.is_rl); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :auth successes %u fails %u", + sp.is_asuc, sp.is_abad); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :sasl successes %u fails %u", + sp.is_ssuc, sp.is_sbad); + sendto_one_numeric(source_p, RPL_STATSDEBUG, "T :Client Server"); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :connected %u %u", sp.is_cl, sp.is_sv); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :bytes sent %lluK %lluK", + sp.is_cbs / 1024, + sp.is_sbs / 1024); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :bytes recv %lluK %lluK", + sp.is_cbr / 1024, + sp.is_sbr / 1024); + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "T :time connected %llu %llu", + sp.is_cti, sp.is_sti); } static void @@ -932,14 +973,14 @@ stats_uptime (struct Client *source_p) { time_t now; - now = CurrentTime - startup_time; - sendto_one_numeric(source_p, RPL_STATSUPTIME, + now = rb_current_time() - startup_time; + sendto_one_numeric(source_p, RPL_STATSUPTIME, form_str (RPL_STATSUPTIME), - now / 86400, (now / 3600) % 24, - (now / 60) % 60, now % 60); + (int)(now / 86400), (int)((now / 3600) % 24), + (int)((now / 60) % 60), (int)(now % 60)); sendto_one_numeric(source_p, RPL_STATSCONN, form_str (RPL_STATSCONN), - MaxConnectionCount, MaxClientCount, + MaxConnectionCount, MaxClientCount, Count.totalrestartcount); } @@ -961,6 +1002,9 @@ static struct shared_flags shared_flagtable[] = { SHARED_UNRESV, 'R' }, { SHARED_LOCOPS, 'L' }, { SHARED_REHASH, 'H' }, + { SHARED_TDLINE, 'd' }, + { SHARED_PDLINE, 'D' }, + { SHARED_UNDLINE, 'E' }, { 0, '\0'} }; @@ -970,7 +1014,7 @@ stats_shared (struct Client *source_p) { struct remote_conf *shared_p; rb_dlink_node *ptr; - char buf[15]; + char buf[sizeof(shared_flagtable)/sizeof(shared_flagtable[0])]; char *p; int i; @@ -990,7 +1034,7 @@ stats_shared (struct Client *source_p) *p = '\0'; - sendto_one_numeric(source_p, RPL_STATSULINE, + sendto_one_numeric(source_p, RPL_STATSULINE, form_str(RPL_STATSULINE), shared_p->server, shared_p->username, shared_p->host, buf); @@ -1012,7 +1056,7 @@ stats_shared (struct Client *source_p) *p = '\0'; - sendto_one_numeric(source_p, RPL_STATSULINE, + sendto_one_numeric(source_p, RPL_STATSULINE, form_str(RPL_STATSULINE), shared_p->server, "*", "*", buf); } @@ -1046,7 +1090,7 @@ stats_servers (struct Client *source_p) target_p = ptr->data; j++; - seconds = CurrentTime - target_p->localClient->firsttime; + seconds = rb_current_time() - target_p->localClient->firsttime; days = (int) (seconds / 86400); seconds %= 86400; @@ -1060,9 +1104,9 @@ stats_servers (struct Client *source_p) "Connected: %d day%s, %d:%02d:%02d", target_p->name, (target_p->serv->by[0] ? target_p->serv->by : "Remote."), - (int) (CurrentTime - target_p->localClient->lasttime), - (int) linebuf_len (&target_p->localClient->buf_sendq), - days, (days == 1) ? "" : "s", hours, minutes, + (int) (rb_current_time() - target_p->localClient->lasttime), + (int) rb_linebuf_len (&target_p->localClient->buf_sendq), + days, (days == 1) ? "" : "s", hours, minutes, (int) seconds); } @@ -1083,7 +1127,7 @@ stats_tgecos(struct Client *source_p) if(aconf->hold) sendto_one_numeric(source_p, RPL_STATSXLINE, form_str(RPL_STATSXLINE), - 'x', aconf->port, aconf->name, + 'x', aconf->port, aconf->host, aconf->passwd); } } @@ -1101,7 +1145,7 @@ stats_gecos(struct Client *source_p) if(!aconf->hold) sendto_one_numeric(source_p, RPL_STATSXLINE, form_str(RPL_STATSXLINE), - 'X', aconf->port, aconf->name, + 'X', aconf->port, aconf->host, aconf->passwd); } } @@ -1119,7 +1163,219 @@ stats_class(struct Client *source_p) static void stats_memory (struct Client *source_p) { - count_memory (source_p); + struct Client *target_p; + struct Channel *chptr; + rb_dlink_node *rb_dlink; + rb_dlink_node *ptr; + int channel_count = 0; + int local_client_conf_count = 0; /* local client conf links */ + int users_counted = 0; /* user structs */ + + int channel_users = 0; + int channel_invites = 0; + int channel_bans = 0; + int channel_except = 0; + int channel_invex = 0; + int channel_quiets = 0; + + int class_count = 0; /* classes */ + int conf_count = 0; /* conf lines */ + int users_invited_count = 0; /* users invited */ + int user_channels = 0; /* users in channels */ + int aways_counted = 0; + size_t number_servers_cached; /* number of servers cached by scache */ + + size_t channel_memory = 0; + size_t channel_ban_memory = 0; + size_t channel_except_memory = 0; + size_t channel_invex_memory = 0; + size_t channel_quiet_memory = 0; + + size_t away_memory = 0; /* memory used by aways */ + size_t ww = 0; /* whowas array count */ + size_t wwm = 0; /* whowas array memory used */ + size_t conf_memory = 0; /* memory used by conf lines */ + size_t mem_servers_cached; /* memory used by scache */ + + size_t linebuf_count = 0; + size_t linebuf_memory_used = 0; + + size_t total_channel_memory = 0; + size_t totww = 0; + + size_t local_client_count = 0; + size_t local_client_memory_used = 0; + + size_t remote_client_count = 0; + size_t remote_client_memory_used = 0; + + size_t total_memory = 0; + + count_whowas_memory(&ww, &wwm); + + RB_DLINK_FOREACH(ptr, global_client_list.head) + { + target_p = ptr->data; + if(MyConnect(target_p)) + { + local_client_conf_count++; + } + + if(target_p->user) + { + users_counted++; + users_invited_count += rb_dlink_list_length(&target_p->user->invited); + user_channels += rb_dlink_list_length(&target_p->user->channel); + if(target_p->user->away) + { + aways_counted++; + away_memory += (strlen(target_p->user->away) + 1); + } + } + } + + /* Count up all channels, ban lists, except lists, Invex lists */ + RB_DLINK_FOREACH(ptr, global_channel_list.head) + { + chptr = ptr->data; + channel_count++; + channel_memory += (strlen(chptr->chname) + sizeof(struct Channel)); + + channel_users += rb_dlink_list_length(&chptr->members); + channel_invites += rb_dlink_list_length(&chptr->invites); + + RB_DLINK_FOREACH(rb_dlink, chptr->banlist.head) + { + channel_bans++; + + channel_ban_memory += sizeof(rb_dlink_node) + sizeof(struct Ban); + } + + RB_DLINK_FOREACH(rb_dlink, chptr->exceptlist.head) + { + channel_except++; + + channel_except_memory += (sizeof(rb_dlink_node) + sizeof(struct Ban)); + } + + RB_DLINK_FOREACH(rb_dlink, chptr->invexlist.head) + { + channel_invex++; + + channel_invex_memory += (sizeof(rb_dlink_node) + sizeof(struct Ban)); + } + + RB_DLINK_FOREACH(rb_dlink, chptr->quietlist.head) + { + channel_quiets++; + + channel_quiet_memory += (sizeof(rb_dlink_node) + sizeof(struct Ban)); + } + } + + /* count up all classes */ + + class_count = rb_dlink_list_length(&class_list) + 1; + + rb_count_rb_linebuf_memory(&linebuf_count, &linebuf_memory_used); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Users %u(%lu) Invites %u(%lu)", + users_counted, + (unsigned long) users_counted * sizeof(struct User), + users_invited_count, + (unsigned long) users_invited_count * sizeof(rb_dlink_node)); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :User channels %u(%lu) Aways %u(%d)", + user_channels, + (unsigned long) user_channels * sizeof(rb_dlink_node), + aways_counted, (int) away_memory); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Attached confs %u(%lu)", + local_client_conf_count, + (unsigned long) local_client_conf_count * sizeof(rb_dlink_node)); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Conflines %u(%d)", conf_count, (int) conf_memory); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Classes %u(%lu)", + class_count, + (unsigned long) class_count * sizeof(struct Class)); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Channels %u(%d)", + channel_count, (int) channel_memory); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Bans %u(%d) Exceptions %u(%d) Invex %u(%d) Quiets %u(%d)", + channel_bans, (int) channel_ban_memory, + channel_except, (int) channel_except_memory, + channel_invex, (int) channel_invex_memory, + channel_quiets, (int) channel_quiet_memory); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Channel members %u(%lu) invite %u(%lu)", + channel_users, + (unsigned long) channel_users * sizeof(rb_dlink_node), + channel_invites, + (unsigned long) channel_invites * sizeof(rb_dlink_node)); + + total_channel_memory = channel_memory + + channel_ban_memory + + channel_users * sizeof(rb_dlink_node) + channel_invites * sizeof(rb_dlink_node); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Whowas array %ld(%ld)", + (long)ww, (long)wwm); + + totww = wwm; + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Hash: client %u(%ld) chan %u(%ld)", + U_MAX, (long)(U_MAX * sizeof(rb_dlink_list)), + CH_MAX, (long)(CH_MAX * sizeof(rb_dlink_list))); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :linebuf %ld(%ld)", + (long)linebuf_count, (long)linebuf_memory_used); + + count_scache(&number_servers_cached, &mem_servers_cached); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :scache %ld(%ld)", + (long)number_servers_cached, (long)mem_servers_cached); + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :hostname hash %d(%ld)", + HOST_MAX, (long)HOST_MAX * sizeof(rb_dlink_list)); + + total_memory = totww + total_channel_memory + conf_memory + + class_count * sizeof(struct Class); + + total_memory += mem_servers_cached; + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Total: whowas %d channel %d conf %d", + (int) totww, (int) total_channel_memory, + (int) conf_memory); + + count_local_client_memory(&local_client_count, &local_client_memory_used); + total_memory += local_client_memory_used; + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Local client Memory in use: %ld(%ld)", + (long)local_client_count, (long)local_client_memory_used); + + + count_remote_client_memory(&remote_client_count, &remote_client_memory_used); + total_memory += remote_client_memory_used; + + sendto_one_numeric(source_p, RPL_STATSDEBUG, + "z :Remote client Memory in use: %ld(%ld)", + (long)remote_client_count, + (long)remote_client_memory_used); } static void @@ -1127,27 +1383,25 @@ stats_ziplinks (struct Client *source_p) { rb_dlink_node *ptr; struct Client *target_p; + struct ZipStats *zipstats; int sent_data = 0; - + char buf[128], buf1[128]; RB_DLINK_FOREACH (ptr, serv_list.head) { target_p = ptr->data; if(IsCapable (target_p, CAP_ZIP)) { - /* we use memcpy(3) and a local copy of the structure to - * work around a register use bug on GCC on the SPARC. - * -jmallett, 04/27/2002 - */ - struct ZipStats zipstats; - memcpy (&zipstats, &target_p->localClient->zipstats, - sizeof (struct ZipStats)); + zipstats = target_p->localClient->zipstats; + sprintf(buf, "%.2f%%", zipstats->out_ratio); + sprintf(buf1, "%.2f%%", zipstats->in_ratio); sendto_one_numeric(source_p, RPL_STATSDEBUG, - "Z :ZipLinks stats for %s send[%.2f%% compression " - "(%lu kB data/%lu kB wire)] recv[%.2f%% compression " - "(%lu kB data/%lu kB wire)]", + "Z :ZipLinks stats for %s send[%s compression " + "(%llu kB data/%llu kB wire)] recv[%s compression " + "(%llu kB data/%llu kB wire)]", target_p->name, - zipstats.out_ratio, zipstats.outK, zipstats.outK_wire, - zipstats.in_ratio, zipstats.inK, zipstats.inK_wire); + buf, zipstats->out >> 10, + zipstats->out_wire >> 10, buf1, + zipstats->in >> 10, zipstats->in_wire >> 10); sent_data++; } } @@ -1164,6 +1418,7 @@ stats_servlinks (struct Client *source_p) struct Client *target_p; rb_dlink_node *ptr; int j = 0; + char buf[128]; if(ConfigServerHide.flatten_links && !IsOper (source_p) && !IsExemptShide(source_p)) @@ -1185,40 +1440,50 @@ stats_servlinks (struct Client *source_p) sendto_one(source_p, Sformat, get_id(&me, source_p), RPL_STATSLINKINFO, get_id(source_p, source_p), - get_server_name(target_p, SHOW_IP), - (int) linebuf_len (&target_p->localClient->buf_sendq), + target_p->name, + (int) rb_linebuf_len (&target_p->localClient->buf_sendq), (int) target_p->localClient->sendM, (int) target_p->localClient->sendK, (int) target_p->localClient->receiveM, (int) target_p->localClient->receiveK, - CurrentTime - target_p->localClient->firsttime, - (CurrentTime > target_p->localClient->lasttime) ? - (CurrentTime - target_p->localClient->lasttime) : 0, + rb_current_time() - target_p->localClient->firsttime, + (rb_current_time() > target_p->localClient->lasttime) ? + (rb_current_time() - target_p->localClient->lasttime) : 0, IsOper (source_p) ? show_capabilities (target_p) : "TS"); } sendto_one_numeric(source_p, RPL_STATSDEBUG, "? :%u total server(s)", j); + snprintf(buf, sizeof buf, "%7.2f", _GMKv ((sendK))); sendto_one_numeric(source_p, RPL_STATSDEBUG, - "? :Sent total : %7.2f %s", - _GMKv (sendK), _GMKs (sendK)); + "? :Sent total : %s %s", + buf, _GMKs (sendK)); + snprintf(buf, sizeof buf, "%7.2f", _GMKv ((receiveK))); sendto_one_numeric(source_p, RPL_STATSDEBUG, - "? :Recv total : %7.2f %s", - _GMKv (receiveK), _GMKs (receiveK)); - - uptime = (CurrentTime - startup_time); + "? :Recv total : %s %s", + buf, _GMKs (receiveK)); - sendto_one_numeric(source_p, RPL_STATSDEBUG, - "? :Server send: %7.2f %s (%4.1f K/s)", - _GMKv (me.localClient->sendK), + uptime = (rb_current_time() - startup_time); + snprintf(buf, sizeof buf, "%7.2f %s (%4.1f K/s)", + _GMKv (me.localClient->sendK), _GMKs (me.localClient->sendK), (float) ((float) me.localClient->sendK / (float) uptime)); - sendto_one_numeric(source_p, RPL_STATSDEBUG, - "? :Server recv: %7.2f %s (%4.1f K/s)", + sendto_one_numeric(source_p, RPL_STATSDEBUG, "? :Server send: %s", buf); + snprintf(buf, sizeof buf, "%7.2f %s (%4.1f K/s)", _GMKv (me.localClient->receiveK), _GMKs (me.localClient->receiveK), (float) ((float) me.localClient->receiveK / (float) uptime)); + sendto_one_numeric(source_p, RPL_STATSDEBUG, "? :Server recv: %s", buf); +} + +static int +stats_l_should_show_oper(struct Client *target_p) +{ + if (IsOperInvis(target_p)) + return 0; + + return 1; } static void @@ -1281,8 +1546,8 @@ stats_ltrace(struct Client *source_p, int parc, const char *parv[]) /* local opers get everyone */ if(MyOper(source_p)) { - stats_l_list(source_p, name, doall, wilds, &unknown_list, statchar); - stats_l_list(source_p, name, doall, wilds, &lclient_list, statchar); + stats_l_list(source_p, name, doall, wilds, &unknown_list, statchar, NULL); + stats_l_list(source_p, name, doall, wilds, &lclient_list, statchar, NULL); } else { @@ -1290,12 +1555,12 @@ stats_ltrace(struct Client *source_p, int parc, const char *parv[]) if(MyClient(source_p)) stats_l_client(source_p, source_p, statchar); - stats_l_list(source_p, name, doall, wilds, &local_oper_list, statchar); + stats_l_list(source_p, name, doall, wilds, &local_oper_list, statchar, stats_l_should_show_oper); } if (!ConfigServerHide.flatten_links || IsOper(source_p) || IsExemptShide(source_p)) - stats_l_list(source_p, name, doall, wilds, &serv_list, statchar); + stats_l_list(source_p, name, doall, wilds, &serv_list, statchar, NULL); return; } @@ -1303,15 +1568,14 @@ stats_ltrace(struct Client *source_p, int parc, const char *parv[]) /* ok, at this point theyre looking for a specific client whos on * our server.. but it contains a wildcard. --fl */ - stats_l_list(source_p, name, doall, wilds, &lclient_list, statchar); + stats_l_list(source_p, name, doall, wilds, &lclient_list, statchar, NULL); return; } - static void stats_l_list(struct Client *source_p, const char *name, int doall, int wilds, - rb_dlink_list * list, char statchar) + rb_dlink_list * list, char statchar, int (*check_fn)(struct Client *target_p)) { rb_dlink_node *ptr; struct Client *target_p; @@ -1327,7 +1591,8 @@ stats_l_list(struct Client *source_p, const char *name, int doall, int wilds, if(!doall && wilds && !match(name, target_p->name)) continue; - stats_l_client(source_p, target_p, statchar); + if (check_fn == NULL || check_fn(target_p)) + stats_l_client(source_p, target_p, statchar); } } @@ -1338,15 +1603,15 @@ stats_l_client(struct Client *source_p, struct Client *target_p, if(IsAnyServer(target_p)) { sendto_one_numeric(source_p, RPL_STATSLINKINFO, Lformat, - get_server_name(target_p, SHOW_IP), - (int) linebuf_len(&target_p->localClient->buf_sendq), + target_p->name, + (int) rb_linebuf_len(&target_p->localClient->buf_sendq), (int) target_p->localClient->sendM, (int) target_p->localClient->sendK, (int) target_p->localClient->receiveM, (int) target_p->localClient->receiveK, - CurrentTime - target_p->localClient->firsttime, - (CurrentTime > target_p->localClient->lasttime) ? - (CurrentTime - target_p->localClient->lasttime) : 0, + rb_current_time() - target_p->localClient->firsttime, + (rb_current_time() > target_p->localClient->lasttime) ? + (rb_current_time() - target_p->localClient->lasttime) : 0, IsOper(source_p) ? show_capabilities(target_p) : "-"); } @@ -1358,18 +1623,31 @@ stats_l_client(struct Client *source_p, struct Client *target_p, get_client_name(target_p, SHOW_IP) : get_client_name(target_p, HIDE_IP)) : get_client_name(target_p, MASK_IP), - (int) linebuf_len(&target_p->localClient->buf_sendq), + (int) rb_linebuf_len(&target_p->localClient->buf_sendq), (int) target_p->localClient->sendM, (int) target_p->localClient->sendK, (int) target_p->localClient->receiveM, (int) target_p->localClient->receiveK, - CurrentTime - target_p->localClient->firsttime, - (CurrentTime > target_p->localClient->lasttime) ? - (CurrentTime - target_p->localClient->lasttime) : 0, + rb_current_time() - target_p->localClient->firsttime, + (rb_current_time() > target_p->localClient->lasttime) ? + (rb_current_time() - target_p->localClient->lasttime) : 0, "-"); } } +static void +rb_dump_fd_callback(int fd, const char *desc, void *data) +{ + struct Client *source_p = data; + sendto_one_numeric(source_p, RPL_STATSDEBUG, "F :fd %-3d desc '%s'", fd, desc); +} + +static void +stats_comm(struct Client *source_p) +{ + rb_dump_fd(rb_dump_fd_callback, source_p); +} + /* * stats_spy *