ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/m_stats.c
Revision: 139
Committed: Sun Oct 16 06:01:13 2005 UTC (20 years, 9 months ago) by db
Content type: text/x-csrc
File size: 46136 byte(s)
Log Message:
- get rid of map_conf_item and unmap_conf_item
- Use an union in struct ConfItem, but only allocate memory needed


File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * m_stats.c: Sends the user statistics or config information.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26     #include "handlers.h" /* m_pass prototype */
27     #include "client.h" /* Client */
28     #include "common.h" /* TRUE/FALSE */
29     #include "ircd.h" /* me */
30     #include "listener.h" /* show_ports */
31     #include "s_gline.h"
32     #include "ircd_handler.h"
33     #include "msg.h" /* Message */
34     #include "hostmask.h"
35     #include "numeric.h" /* ERR_xxx */
36     #include "send.h" /* sendto_one */
37     #include "s_conf.h" /* AccessItem, report_configured_links */
38     #include "s_serv.h" /* hunt_server */
39     #include "s_stats.h" /* tstats */
40     #include "s_user.h" /* show_opers */
41     #include "parse.h"
42     #include "modules.h"
43     #include "resv.h" /* report_resv */
44     #include "whowas.h"
45    
46     static void do_stats(struct Client *, int, char **);
47     static void m_stats(struct Client *, struct Client *, int, char *[]);
48     static void mo_stats(struct Client *, struct Client *, int, char *[]);
49     static void ms_stats(struct Client *, struct Client *, int, char *[]);
50    
51     struct Message stats_msgtab = {
52     "STATS", 0, 0, 2, 0, MFLG_SLOW, 0,
53     { m_unregistered, m_stats, ms_stats, m_ignore, mo_stats, m_ignore }
54     };
55    
56     #ifndef STATIC_MODULES
57 knight 31 const char *_version = "$Revision$";
58 adx 30 static struct Callback *stats_cb;
59    
60     static void *
61     va_stats(va_list args)
62     {
63     struct Client *source_p = va_arg(args, struct Client *);
64     int parc = va_arg(args, int);
65     char **parv = va_arg(args, char **);
66    
67     do_stats(source_p, parc, parv);
68     return NULL;
69     }
70    
71     void
72     _modinit(void)
73     {
74     stats_cb = register_callback("doing_stats", va_stats);
75     mod_add_cmd(&stats_msgtab);
76     }
77    
78     void
79     _moddeinit(void)
80     {
81     mod_del_cmd(&stats_msgtab);
82     uninstall_hook(stats_cb, va_stats);
83     }
84     #endif
85    
86     static char *parse_stats_args(int, char **, int *, int *);
87     static void stats_L(struct Client *, char *, int, int, char);
88     static void stats_L_list(struct Client *s, char *, int, int, dlink_list *, char);
89    
90     static void stats_dns_servers(struct Client *);
91     static void stats_connect(struct Client *);
92     static void stats_deny(struct Client *);
93     static void stats_tdeny(struct Client *);
94     static void stats_exempt(struct Client *);
95     static void stats_events(struct Client *);
96     static void stats_pending_glines(struct Client *);
97     static void stats_glines(struct Client *);
98     static void stats_gdeny(struct Client *);
99     static void stats_hubleaf(struct Client *);
100     static void stats_auth(struct Client *);
101     static void stats_tklines(struct Client *);
102     static void stats_klines(struct Client *);
103     static void stats_messages(struct Client *);
104     static void stats_oper(struct Client *);
105     static void stats_operedup(struct Client *);
106     static void stats_ports(struct Client *);
107     static void stats_resv(struct Client *);
108     static void stats_usage(struct Client *);
109     static void stats_tstats(struct Client *);
110     static void stats_uptime(struct Client *);
111     static void stats_shared(struct Client *);
112     static void stats_servers(struct Client *);
113     static void stats_gecos(struct Client *);
114     static void stats_class(struct Client *);
115     static void stats_memory(struct Client *);
116     static void stats_servlinks(struct Client *);
117     static void stats_ltrace(struct Client *, int, char **);
118     static void stats_ziplinks(struct Client *);
119 adx 65 static void stats_hooks(struct Client *);
120 adx 68 static void fd_dump(struct Client *);
121 adx 30
122     /* This table contains the possible stats items, in order:
123     * /stats name, function to call, operonly? adminonly? /stats letter
124     * case only matters in the stats letter column.. -- fl_ */
125     static const struct StatsStruct
126     {
127     const unsigned char letter;
128     void (*handler)();
129     const unsigned int need_oper;
130     const unsigned int need_admin;
131     } stats_cmd_table[] = {
132     /* letter function need_oper need_admin */
133     { 'a', stats_dns_servers, 1, 1, },
134     { 'A', stats_dns_servers, 1, 1, },
135     { 'c', stats_connect, 1, 0, },
136     { 'C', stats_connect, 1, 0, },
137     { 'd', stats_tdeny, 1, 0, },
138     { 'D', stats_deny, 1, 0, },
139     { 'e', stats_exempt, 1, 0, },
140     { 'E', stats_events, 1, 1, },
141     { 'f', fd_dump, 1, 1, },
142     { 'F', fd_dump, 1, 1, },
143     { 'g', stats_pending_glines, 1, 0, },
144     { 'G', stats_glines, 1, 0, },
145     { 'h', stats_hooks, 1, 1, },
146     { 'H', stats_hubleaf, 1, 0, },
147     { 'i', stats_auth, 0, 0, },
148     { 'I', stats_auth, 0, 0, },
149     { 'k', stats_tklines, 0, 0, },
150     { 'K', stats_klines, 0, 0, },
151     { 'l', stats_ltrace, 1, 0, },
152     { 'L', stats_ltrace, 1, 0, },
153     { 'm', stats_messages, 0, 0, },
154     { 'M', stats_messages, 0, 0, },
155     { 'o', stats_oper, 0, 0, },
156     { 'O', stats_oper, 0, 0, },
157     { 'p', stats_operedup, 0, 0, },
158     { 'P', stats_ports, 0, 0, },
159     { 'q', stats_resv, 1, 0, },
160     { 'Q', stats_resv, 1, 0, },
161     { 'r', stats_usage, 1, 0, },
162     { 'R', stats_usage, 1, 0, },
163     { 't', stats_tstats, 1, 0, },
164     { 'T', stats_tstats, 1, 0, },
165     { 'u', stats_uptime, 0, 0, },
166     { 'U', stats_shared, 1, 0, },
167     { 'v', stats_servers, 1, 0, },
168     { 'V', stats_gdeny, 1, 0, },
169     { 'x', stats_gecos, 1, 0, },
170     { 'X', stats_gecos, 1, 0, },
171     { 'y', stats_class, 1, 0, },
172     { 'Y', stats_class, 1, 0, },
173     { 'z', stats_memory, 1, 0, },
174     { 'Z', stats_ziplinks, 1, 0, },
175     { '?', stats_servlinks, 0, 0, },
176     { '\0', (void(*)())0, 0, 0, }
177     };
178    
179     const char *from, *to;
180    
181     static void
182     do_stats(struct Client *source_p, int parc, char **parv)
183     {
184     char statchar = *parv[1];
185     int i;
186    
187     if (statchar == '\0')
188     {
189     sendto_one(source_p, form_str(RPL_ENDOFSTATS),
190     from, to, '*');
191     return;
192     }
193    
194     for (i = 0; stats_cmd_table[i].handler; i++)
195     {
196     if (stats_cmd_table[i].letter == statchar)
197     {
198     /* The stats table says what privs are needed, so check --fl_ */
199     if ((stats_cmd_table[i].need_admin && !IsAdmin(source_p)) ||
200     (stats_cmd_table[i].need_oper && !IsOper(source_p)))
201     {
202     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
203     from, to);
204     break;
205     }
206    
207     /* Blah, stats L needs the parameters, none of the others do.. */
208     if (statchar == 'L' || statchar == 'l')
209     stats_cmd_table[i].handler(source_p, parc, parv);
210     else
211     stats_cmd_table[i].handler(source_p);
212    
213     break;
214     }
215     }
216    
217     sendto_one(source_p, form_str(RPL_ENDOFSTATS),
218     from, to, statchar);
219     }
220    
221     /*
222     * m_stats()
223     * parv[0] = sender prefix
224     * parv[1] = stat letter/command
225     * parv[2] = (if present) server/mask in stats L
226     *
227     * This will search the tables for the appropriate stats letter/command,
228     * if found execute it.
229     */
230     static void
231     m_stats(struct Client *client_p, struct Client *source_p,
232     int parc, char *parv[])
233     {
234     static time_t last_used = 0;
235    
236     /* Is the stats meant for us? */
237     if (!ConfigFileEntry.disable_remote)
238     if (hunt_server(client_p,source_p,":%s STATS %s :%s",2,parc,parv) != HUNTED_ISME)
239     return;
240    
241     if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
242     {
243     from = me.id;
244     to = source_p->id;
245     }
246     else
247     {
248     from = me.name;
249     to = source_p->name;
250     }
251    
252     /* Check the user is actually allowed to do /stats, and isnt flooding */
253     if ((last_used + ConfigFileEntry.pace_wait) > CurrentTime)
254     {
255     sendto_one(source_p,form_str(RPL_LOAD2HI),
256     from, to);
257     return;
258     }
259     else
260     last_used = CurrentTime;
261    
262     #ifdef STATIC_MODULES
263     do_stats(source_p, parc, parv);
264     #else
265     execute_callback(stats_cb, source_p, parc, parv);
266     #endif
267     }
268    
269     /*
270     * mo_stats()
271     * parv[0] = sender prefix
272     * parv[1] = stat letter/command
273     * parv[2] = (if present) server/mask in stats L, or target
274     *
275     * This will search the tables for the appropriate stats letter,
276     * if found execute it.
277     */
278     static void
279     mo_stats(struct Client *client_p, struct Client *source_p,
280     int parc, char *parv[])
281     {
282     if (hunt_server(client_p, source_p, ":%s STATS %s :%s", 2,
283     parc, parv) != HUNTED_ISME)
284     return;
285    
286     if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
287     {
288     from = me.id;
289     to = source_p->id;
290     }
291     else
292     {
293     from = me.name;
294     to = source_p->name;
295     }
296    
297     #ifdef STATIC_MODULES
298     do_stats(source_p, parc, parv);
299     #else
300     execute_callback(stats_cb, source_p, parc, parv);
301     #endif
302     }
303    
304     /*
305     * This is part of the STATS replies. There is no offical numeric for this
306     * since this isnt an official command, in much the same way as HASH isnt.
307     * It is also possible that some systems wont support this call or have
308     * different field names for "struct rusage".
309     * -avalon
310     */
311     static void
312     send_usage(struct Client *source_p)
313     {
314     #ifndef _WIN32
315     struct rusage rus;
316     time_t secs;
317     time_t rup;
318     #ifdef hz
319     # define hzz hz
320     #else
321     # ifdef HZ
322     # define hzz HZ
323     # else
324     int hzz = 1;
325     # endif
326     #endif
327    
328     if (getrusage(RUSAGE_SELF, &rus) == -1)
329     {
330     sendto_one(source_p, ":%s NOTICE %s :Getruseage error: %s",
331     me.name, source_p->name, strerror(errno));
332     return;
333     }
334    
335     secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec;
336    
337     if (secs == 0)
338     secs = 1;
339    
340     rup = (CurrentTime - me.since) * hzz;
341    
342     if (rup == 0)
343     rup = 1;
344    
345     sendto_one(source_p,
346     ":%s %d %s R :CPU Secs %d:%d User %d:%d System %d:%d",
347     me.name, RPL_STATSDEBUG, source_p->name, (int)(secs/60), (int)(secs%60),
348     (int)(rus.ru_utime.tv_sec/60), (int)(rus.ru_utime.tv_sec%60),
349     (int)(rus.ru_stime.tv_sec/60), (int)(rus.ru_stime.tv_sec%60));
350     sendto_one(source_p, ":%s %d %s R :RSS %ld ShMem %ld Data %ld Stack %ld",
351     me.name, RPL_STATSDEBUG, source_p->name, rus.ru_maxrss,
352     (rus.ru_ixrss / rup), (rus.ru_idrss / rup),
353     (rus.ru_isrss / rup));
354     sendto_one(source_p, ":%s %d %s R :Swaps %d Reclaims %d Faults %d",
355     me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_nswap,
356     (int)rus.ru_minflt, (int)rus.ru_majflt);
357     sendto_one(source_p, ":%s %d %s R :Block in %d out %d",
358     me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_inblock,
359     (int)rus.ru_oublock);
360     sendto_one(source_p, ":%s %d %s R :Msg Rcv %d Send %d",
361     me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_msgrcv,
362     (int)rus.ru_msgsnd);
363     sendto_one(source_p, ":%s %d %s R :Signals %d Context Vol. %d Invol %d",
364     me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_nsignals,
365     (int)rus.ru_nvcsw, (int)rus.ru_nivcsw);
366     #endif
367     }
368    
369     static void
370     count_memory(struct Client *source_p)
371     {
372 adx 62 BlockHeap *bh;
373 adx 30 const dlink_node *gptr = NULL;
374     const dlink_node *dlink = NULL;
375    
376     int local_client_conf_count = 0; /* local client conf links */
377     int users_counted = 0; /* user structs */
378    
379     int channel_users = 0; /* XXX */
380     int channel_invites = 0;
381     int channel_bans = 0;
382     int channel_except = 0;
383     int channel_invex = 0;
384    
385     int wwu = 0; /* whowas users */
386     int class_count = 0; /* classes */
387     int users_invited_count = 0; /* users invited */
388     int aways_counted = 0;
389     int number_ips_stored; /* number of ip addresses hashed */
390    
391     unsigned long channel_memory = 0;
392     size_t channel_ban_memory = 0;
393     size_t channel_except_memory = 0;
394     size_t channel_invex_memory = 0;
395    
396     unsigned int safelist_count = 0;
397     size_t safelist_memory = 0;
398    
399     unsigned long away_memory = 0; /* memory used by aways */
400     unsigned long wwm = 0; /* whowas array memory used */
401     unsigned long conf_memory = 0; /* memory used by conf lines */
402     unsigned long mem_ips_stored; /* memory used by ip address hash */
403    
404     unsigned long client_hash_table_size = 0;
405     unsigned long channel_hash_table_size = 0;
406     unsigned long resv_hash_table_size = 0;
407     unsigned long id_hash_table_size = 0;
408     unsigned long total_channel_memory = 0;
409     unsigned long totww = 0;
410    
411     unsigned int local_client_count = 0;
412     unsigned int remote_client_count = 0;
413    
414     unsigned int local_client_memory_used = 0;
415     unsigned int remote_client_memory_used = 0;
416    
417     unsigned long total_memory = 0;
418     unsigned int topic_count = 0;
419    
420     count_whowas_memory(&wwu, &wwm);
421    
422     DLINK_FOREACH(gptr, global_client_list.head)
423     {
424     struct Client *target_p = gptr->data;
425    
426     if (MyConnect(target_p))
427     {
428     ++local_client_count;
429 db 101 #if 0 /* XXX */
430 adx 30 local_client_conf_count += dlink_list_length(&target_p->localClient->confs);
431 db 101 #endif
432 adx 30 }
433     else
434     ++remote_client_count;
435    
436     if (IsClient(target_p))
437     {
438     ++users_counted;
439     users_invited_count += dlink_list_length(&target_p->invited);
440    
441     if (target_p->away != NULL)
442     {
443     ++aways_counted;
444     away_memory += strlen(target_p->away) + 1;
445     }
446     }
447     }
448    
449     /* Count up all channels, ban lists, except lists, Invex lists */
450     channel_memory = dlink_list_length(&global_channel_list) *
451     sizeof(struct Channel);
452     DLINK_FOREACH(gptr, global_channel_list.head)
453     {
454     struct Ban *actualBan;
455     struct Channel *chptr = gptr->data;
456    
457     channel_users += dlink_list_length(&chptr->members);
458     channel_invites += dlink_list_length(&chptr->invites);
459    
460     if (chptr->topic != NULL)
461     ++topic_count;
462    
463     if ((channel_bans = dlink_list_length(&chptr->banlist)))
464     {
465     channel_ban_memory = channel_bans * sizeof(struct Ban);
466    
467     DLINK_FOREACH(dlink, chptr->banlist.head)
468     {
469     actualBan = dlink->data;
470     assert(actualBan->who);
471    
472     channel_ban_memory += actualBan->len + 3;
473     channel_ban_memory += strlen(actualBan->who) + 1;
474     }
475     }
476    
477     if ((channel_except = dlink_list_length(&chptr->exceptlist)))
478     {
479     channel_except_memory = channel_except * sizeof(struct Ban);
480    
481     DLINK_FOREACH(dlink, chptr->exceptlist.head)
482     {
483     actualBan = dlink->data;
484     assert(actualBan->who);
485    
486     channel_except_memory += actualBan->len + 3;
487     channel_except_memory += strlen(actualBan->who) + 1;
488     }
489     }
490    
491     if ((channel_invex = dlink_list_length(&chptr->invexlist)))
492     {
493     channel_invex_memory = channel_invex * sizeof(struct Ban);
494    
495     DLINK_FOREACH(dlink, chptr->invexlist.head)
496     {
497     actualBan = dlink->data;
498     assert(actualBan->who);
499    
500     channel_invex_memory += actualBan->len + 3;
501     channel_invex_memory += strlen(actualBan->who) + 1;
502     }
503     }
504     }
505    
506     if ((safelist_count = dlink_list_length(&listing_client_list)))
507     {
508     safelist_memory = safelist_count * sizeof(struct ListTask);
509     DLINK_FOREACH(gptr, listing_client_list.head)
510     {
511     struct Client *acptr = gptr->data;
512    
513     DLINK_FOREACH(dlink, acptr->localClient->list_task->show_mask.head)
514     safelist_memory += strlen(dlink->data);
515    
516     DLINK_FOREACH(dlink, acptr->localClient->list_task->hide_mask.head)
517     safelist_memory += strlen(dlink->data);
518     }
519     }
520    
521     #if 0
522     /* XXX THIS has to be fixed !!!! -db */
523     /* count up all config items */
524     DLINK_FOREACH(dlink, ConfigItemList.head)
525     {
526     aconf = dlink->data;
527     conf_memory += aconf->host ? strlen(aconf->host)+1 : 0;
528     conf_memory += aconf->passwd ? strlen(aconf->passwd)+1 : 0;
529     conf_memory += aconf->name ? strlen(aconf->name)+1 : 0;
530     conf_memory += sizeof(struct AccessItem);
531     }
532     #endif
533     /* count up all classes */
534     class_count = dlink_list_length(&class_items);
535    
536     sendto_one(source_p, ":%s %d %s z :Clients %u(%lu) Invites %u(%lu)",
537     me.name, RPL_STATSDEBUG, source_p->name, users_counted,
538     (unsigned long)(users_counted * sizeof(struct Client)),
539     users_invited_count, (unsigned long)(users_invited_count * sizeof(dlink_node)));
540    
541     sendto_one(source_p, ":%s %d %s z :User aways %u(%d)",
542     me.name, RPL_STATSDEBUG, source_p->name,
543     aways_counted, (int)away_memory);
544    
545     sendto_one(source_p, ":%s %d %s z :Attached confs %u(%lu)",
546     me.name, RPL_STATSDEBUG, source_p->name,
547     local_client_conf_count,
548     (unsigned long)(local_client_conf_count * sizeof(dlink_node)));
549    
550     /* XXX ConfigItemList fix */
551     #if 0
552     sendto_one(source_p, ":%s %d %s z :Conflines %lu(%d)",
553     me.name, RPL_STATSDEBUG, source_p->name,
554     dlink_list_length(&ConfigItemList), (int) conf_memory);
555     #endif
556    
557     sendto_one(source_p, ":%s %d %s z :Resv channels %lu(%lu) nicks %lu(%lu)",
558     me.name, RPL_STATSDEBUG, source_p->name,
559     dlink_list_length(&resv_channel_list),
560     dlink_list_length(&resv_channel_list) * sizeof(struct ResvChannel),
561     dlink_list_length(&nresv_items),
562     dlink_list_length(&nresv_items) * sizeof(struct MatchItem));
563    
564     sendto_one(source_p, ":%s %d %s z :Classes %u(%lu)",
565     me.name, RPL_STATSDEBUG, source_p->name,
566     class_count, (unsigned long)(class_count * sizeof(struct ClassItem)));
567    
568     sendto_one(source_p, ":%s %d %s z :Channels %lu(%lu) Topics %u(%d)",
569     me.name, RPL_STATSDEBUG, source_p->name,
570     dlink_list_length(&global_channel_list),
571     channel_memory, topic_count, topic_count *
572     (TOPICLEN + 1 + USERHOST_REPLYLEN));
573    
574     sendto_one(source_p, ":%s %d %s z :Bans %u(%u)",
575     me.name, RPL_STATSDEBUG, source_p->name,
576     channel_bans, channel_ban_memory);
577    
578     sendto_one(source_p, ":%s %d %s z :Exceptions %u(%u)",
579     me.name, RPL_STATSDEBUG, source_p->name,
580     channel_except, channel_except_memory);
581    
582     sendto_one(source_p, ":%s %d %s z :Invex %u(%u)",
583     me.name, RPL_STATSDEBUG, source_p->name,
584     channel_invex, channel_invex_memory);
585    
586     sendto_one(source_p, ":%s %d %s z :Channel members %u(%lu) invite %u(%lu)",
587     me.name, RPL_STATSDEBUG, source_p->name, channel_users,
588     (unsigned long)(channel_users * sizeof(struct Membership)),
589     channel_invites, (unsigned long)channel_invites *
590     sizeof(dlink_node));
591    
592     total_channel_memory = channel_memory + channel_ban_memory +
593     channel_users * sizeof(struct Membership) +
594     channel_invites * sizeof(dlink_node);
595    
596     sendto_one(source_p, ":%s %d %s z :Safelist %u(%u)",
597     me.name, RPL_STATSDEBUG, source_p->name,
598     safelist_count, safelist_memory);
599    
600     sendto_one(source_p, ":%s %d %s z :Whowas users %u(%lu)",
601     me.name, RPL_STATSDEBUG, source_p->name,
602     wwu, (unsigned long)(wwu * sizeof(struct Client)));
603    
604     sendto_one(source_p, ":%s %d %s z :Whowas array %u(%d)",
605     me.name, RPL_STATSDEBUG, source_p->name,
606     NICKNAMEHISTORYLENGTH, (int)wwm);
607    
608     totww = wwu * sizeof(struct Client) + wwm;
609     /****
610     client_hash_table_size = hash_get_client_table_size();
611     channel_hash_table_size = hash_get_channel_table_size();
612     resv_hash_table_size = hash_get_resv_table_size();
613     id_hash_table_size = hash_get_id_table_size();
614    
615     sendto_one(source_p, ":%s %d %s z :Hash: client %u(%lu) chan %u(%lu) resv "
616     "%u(%lu) id %u(%lu)",
617     me.name, RPL_STATSDEBUG, source_p->name,
618     U_MAX, client_hash_table_size,
619     CH_MAX, channel_hash_table_size , R_MAX,
620     resv_hash_table_size, U_MAX, id_hash_table_size);
621     ****/
622     count_ip_hash(&number_ips_stored,&mem_ips_stored);
623     sendto_one(source_p, ":%s %d %s z :iphash %u(%d)",
624     me.name, RPL_STATSDEBUG, source_p->name,
625     number_ips_stored, (int)mem_ips_stored);
626    
627     total_memory = totww + total_channel_memory + conf_memory + class_count *
628     sizeof(struct ClassItem);
629     total_memory += client_hash_table_size;
630     total_memory += channel_hash_table_size;
631     total_memory += resv_hash_table_size;
632     total_memory += id_hash_table_size;
633    
634     sendto_one(source_p, ":%s %d %s z :Total: whowas %d channel %d conf %d",
635     me.name, RPL_STATSDEBUG, source_p->name, (int)totww,
636     (int)total_channel_memory, (int)conf_memory);
637    
638     local_client_memory_used = local_client_count*(sizeof(struct Client) + sizeof(struct LocalUser));
639     total_memory += local_client_memory_used;
640     sendto_one(source_p, ":%s %d %s z :Local client Memory in use: %d(%d)",
641     me.name, RPL_STATSDEBUG, source_p->name, local_client_count,
642     local_client_memory_used);
643    
644     remote_client_memory_used = remote_client_count * sizeof(struct Client);
645     total_memory += remote_client_memory_used;
646     sendto_one(source_p, ":%s %d %s z :Remote client Memory in use: %d(%d)",
647     me.name, RPL_STATSDEBUG, source_p->name, remote_client_count,
648     remote_client_memory_used);
649    
650 adx 62 for (bh = heap_list; bh != NULL; bh = bh->next)
651     sendto_one(source_p, ":%s %d %s z :%s mempool: used %u/%u free %u/%u (size %u/%u)",
652     me.name, RPL_STATSDEBUG, source_p->name, bh->name,
653     block_heap_get_used_elm(bh),
654     block_heap_get_used_mem(bh),
655     block_heap_get_free_elm(bh),
656     block_heap_get_free_mem(bh),
657     block_heap_get_size_elm(bh),
658     block_heap_get_size_mem(bh));
659 adx 30
660     sendto_one(source_p,
661     ":%s %d %s z :TOTAL: %d Available: Current max RSS: %lu",
662     me.name, RPL_STATSDEBUG, source_p->name,
663     (int)total_memory, get_maxrss());
664     }
665    
666     static void
667     stats_connect(struct Client *source_p)
668     {
669     report_confitem_types(source_p, SERVER_TYPE, 0);
670     }
671    
672     /* stats_deny()
673     *
674     * input - client to report to
675     * output - none
676     * side effects - client is given dline list.
677     */
678     static void
679     stats_deny(struct Client *source_p)
680     {
681     struct AddressRec *arec;
682     struct ConfItem *conf;
683     struct AccessItem *aconf;
684     int i;
685    
686     for (i = 0; i < ATABLE_SIZE; i++)
687     {
688     for (arec = atable[i]; arec; arec=arec->next)
689     {
690     if (arec->type == CONF_DLINE)
691     {
692     aconf = arec->aconf;
693    
694     /* dont report a tdline as a dline */
695     if (aconf->flags & CONF_FLAGS_TEMPORARY)
696     continue;
697    
698 db 139 conf = aconf->conf;
699 adx 30
700     sendto_one(source_p, form_str(RPL_STATSDLINE),
701     from, to, 'D', aconf->host, aconf->reason,
702     aconf->oper_reason);
703     }
704     }
705     }
706     }
707    
708     /* stats_tdeny()
709     *
710     * input - client to report to
711     * output - none
712     * side effects - client is given dline list.
713     */
714     static void
715     stats_tdeny(struct Client *source_p)
716     {
717     struct AddressRec *arec;
718     struct ConfItem *conf;
719     struct AccessItem *aconf;
720     int i;
721    
722     for (i = 0; i < ATABLE_SIZE; i++)
723     {
724     for (arec = atable[i]; arec; arec=arec->next)
725     {
726     if (arec->type == CONF_DLINE)
727     {
728     aconf = arec->aconf;
729    
730     /* dont report a permanent dline as a tdline */
731     if (!(aconf->flags & CONF_FLAGS_TEMPORARY))
732     continue;
733    
734 db 139 conf = aconf->conf;
735 adx 30
736     sendto_one(source_p, form_str(RPL_STATSDLINE),
737     from, to, 'd', aconf->host, aconf->reason,
738     aconf->oper_reason);
739     }
740     }
741     }
742     }
743    
744     /* stats_exempt()
745     *
746     * input - client to report to
747     * output - none
748     * side effects - client is given list of exempt blocks
749     */
750     static void
751     stats_exempt(struct Client *source_p)
752     {
753     struct AddressRec *arec;
754     struct ConfItem *conf;
755     struct AccessItem *aconf;
756     int i;
757    
758     for (i = 0; i < ATABLE_SIZE; i++)
759     {
760     for (arec = atable[i]; arec; arec=arec->next)
761     {
762     if (arec->type == CONF_EXEMPTDLINE)
763     {
764     aconf = arec->aconf;
765    
766 db 139 conf = aconf->conf;
767 adx 30
768     sendto_one(source_p, form_str(RPL_STATSDLINE),
769     from, to, 'e', aconf->host,
770     aconf->reason, aconf->oper_reason);
771     }
772     }
773     }
774     }
775    
776     /* stats_pending_glines()
777     *
778     * input - client pointer
779     * output - none
780     * side effects - client is shown list of pending glines
781     */
782     static void
783     stats_pending_glines(struct Client *source_p)
784     {
785     #ifdef GLINE_VOTING
786     dlink_node *pending_node;
787     struct gline_pending *glp_ptr;
788     char timebuffer[MAX_DATE_STRING];
789     struct tm *tmptr;
790    
791     if (!ConfigFileEntry.glines)
792     {
793     sendto_one(source_p, ":%s NOTICE %s :This server does not support G-Lines",
794     from, to);
795     return;
796     }
797    
798     if (dlink_list_length(&pending_glines) > 0)
799     sendto_one(source_p, ":%s NOTICE %s :Pending G-lines",
800     from, to);
801    
802     DLINK_FOREACH(pending_node, pending_glines.head)
803     {
804     glp_ptr = pending_node->data;
805     tmptr = localtime(&glp_ptr->time_request1);
806     strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
807    
808     sendto_one(source_p,
809     ":%s NOTICE %s :1) %s!%s@%s on %s requested gline at %s for %s@%s [%s]",
810     from, to, glp_ptr->oper_nick1,
811     glp_ptr->oper_user1, glp_ptr->oper_host1,
812     glp_ptr->oper_server1, timebuffer,
813     glp_ptr->user, glp_ptr->host, glp_ptr->reason1);
814    
815     if (glp_ptr->oper_nick2[0] != '\0')
816     {
817     tmptr = localtime(&glp_ptr->time_request2);
818     strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
819     sendto_one(source_p,
820     ":%s NOTICE %s :2) %s!%s@%s on %s requested gline at %s for %s@%s [%s]",
821     from, to, glp_ptr->oper_nick2,
822     glp_ptr->oper_user2, glp_ptr->oper_host2,
823     glp_ptr->oper_server2, timebuffer,
824     glp_ptr->user, glp_ptr->host, glp_ptr->reason2);
825     }
826     }
827    
828     sendto_one(source_p, ":%s NOTICE %s :End of Pending G-lines",
829     from, to);
830     #else
831     sendto_one(source_p, ":%s NOTICE %s :This server does not support G-Line voting",
832     from, to);
833     #endif /* GLINE VOTING */
834     }
835    
836     /* stats_glines()
837     *
838     * input - client pointer
839     * output - none
840     * side effects - client is shown list of glines
841     */
842     static void
843     stats_glines(struct Client *source_p)
844     {
845     struct AddressRec *arec = NULL;
846     int i = 0;
847    
848     if (!ConfigFileEntry.glines)
849     {
850     sendto_one(source_p, ":%s NOTICE %s :This server does not support G-Lines",
851     from, to);
852     return;
853     }
854    
855     for (; i < ATABLE_SIZE; ++i)
856     {
857     for (arec = atable[i]; arec; arec=arec->next)
858     {
859     if (arec->type == CONF_GLINE)
860     {
861     const struct AccessItem *aconf = arec->aconf;
862    
863     sendto_one(source_p, form_str(RPL_STATSKLINE),
864     from, to, "G",
865     aconf->host ? aconf->host : "*",
866     aconf->user ? aconf->user : "*",
867     aconf->reason ? aconf->reason : "No reason", "" );
868     }
869     }
870     }
871     }
872    
873     /* stats_gdeny()
874     *
875     * input - client pointer
876     * outputs - none
877     * side effects - client is shown gline ACL
878     */
879     static void
880     stats_gdeny(struct Client *source_p)
881     {
882     if (!ConfigFileEntry.glines)
883     {
884     sendto_one(source_p, ":%s NOTICE %s :This server does not support G-Lines",
885     from, to);
886     return;
887     }
888    
889     report_confitem_types(source_p, GDENY_TYPE, 0);
890     }
891    
892     static void
893     stats_hubleaf(struct Client *source_p)
894     {
895     report_confitem_types(source_p, HUB_TYPE, 0);
896     report_confitem_types(source_p, LEAF_TYPE, 0);
897     }
898    
899     static void
900     stats_auth(struct Client *source_p)
901     {
902     /* Oper only, if unopered, return ERR_NOPRIVILEGES */
903     if ((ConfigFileEntry.stats_i_oper_only == 2) && !IsOper(source_p))
904     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
905     from, to);
906    
907     /* If unopered, Only return matching auth blocks */
908     else if ((ConfigFileEntry.stats_i_oper_only == 1) && !IsOper(source_p))
909     {
910     struct ConfItem *conf;
911     struct AccessItem *aconf;
912    
913     if (MyConnect(source_p))
914     aconf = find_conf_by_address(source_p->host,
915     &source_p->localClient->ip,
916     CONF_CLIENT,
917     source_p->localClient->aftype,
918     source_p->username,
919     source_p->localClient->passwd);
920     else
921     aconf = find_conf_by_address(source_p->host, NULL, CONF_CLIENT,
922     0, source_p->username, NULL);
923    
924     if (aconf == NULL)
925     return;
926    
927 db 139 conf = aconf->conf;
928 adx 30
929     sendto_one(source_p, form_str(RPL_STATSILINE), from,
930     to, 'I',
931     "*", show_iline_prefix(source_p, aconf, aconf->user),
932     aconf->host, aconf->port,
933     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
934     }
935     /* They are opered, or allowed to see all auth blocks */
936     else
937     report_auth(source_p);
938     }
939    
940     static void
941     stats_tklines(struct Client *source_p)
942     {
943     struct ConfItem *conf;
944     /* Oper only, if unopered, return ERR_NOPRIVILEGES */
945     if ((ConfigFileEntry.stats_k_oper_only == 2) && !IsOper(source_p))
946     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
947     from, to);
948    
949     /* If unopered, Only return matching klines */
950     else if ((ConfigFileEntry.stats_k_oper_only == 1) && !IsOper(source_p))
951     {
952     struct AccessItem *aconf;
953    
954     if (MyConnect(source_p))
955     aconf = find_conf_by_address(source_p->host,
956     &source_p->localClient->ip,
957     CONF_KILL,
958     source_p->localClient->aftype,
959     source_p->username, NULL);
960     else
961     aconf = find_conf_by_address(source_p->host, NULL, CONF_KILL,
962     0, source_p->username, NULL);
963    
964     if (aconf == NULL)
965     return;
966    
967     /* dont report a permanent kline as a tkline */
968     if (!(aconf->flags & CONF_FLAGS_TEMPORARY))
969     return;
970    
971 db 139 conf = aconf->conf;
972 adx 30
973     sendto_one(source_p, form_str(RPL_STATSKLINE), from,
974     to, "k", aconf->host, aconf->user, aconf->reason, "");
975     }
976     /* Theyre opered, or allowed to see all klines */
977     else {
978     report_Klines(source_p, 1);
979     report_confitem_types(source_p, RKLINE_TYPE, 1);
980     }
981     }
982    
983     static void
984     stats_klines(struct Client *source_p)
985     {
986     /* Oper only, if unopered, return ERR_NOPRIVILEGES */
987     if ((ConfigFileEntry.stats_k_oper_only == 2) && !IsOper(source_p))
988     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
989     from, to);
990    
991     /* If unopered, Only return matching klines */
992     else if ((ConfigFileEntry.stats_k_oper_only == 1) && !IsOper(source_p))
993     {
994     struct AccessItem *aconf;
995    
996     /* search for a kline */
997     if(MyConnect(source_p))
998     aconf = find_conf_by_address(source_p->host,
999     &source_p->localClient->ip,
1000     CONF_KILL,
1001     source_p->localClient->aftype,
1002     source_p->username, NULL);
1003     else
1004     aconf = find_conf_by_address(source_p->host, NULL, CONF_KILL,
1005     0, source_p->username, NULL);
1006    
1007     if(aconf == NULL)
1008     return;
1009    
1010     /* dont report a tkline as a kline */
1011     if(aconf->flags & CONF_FLAGS_TEMPORARY)
1012     return;
1013    
1014     sendto_one(source_p, form_str(RPL_STATSKLINE), from,
1015     to, "K", aconf->host, aconf->user, aconf->reason,
1016     aconf->oper_reason);
1017     }
1018     /* Theyre opered, or allowed to see all klines */
1019     else {
1020     report_Klines(source_p, 0);
1021     report_confitem_types(source_p, RKLINE_TYPE, 0);
1022     }
1023     }
1024    
1025     static void
1026     stats_messages(struct Client *source_p)
1027     {
1028     report_messages(source_p);
1029     }
1030    
1031     static void
1032     stats_oper(struct Client *source_p)
1033     {
1034     if (!IsOper(source_p) && ConfigFileEntry.stats_o_oper_only)
1035     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1036     from, to);
1037     else
1038     report_confitem_types(source_p, OPER_TYPE, 0);
1039     }
1040    
1041     /* stats_operedup()
1042     *
1043     * input - client pointer
1044     * output - none
1045     * side effects - client is shown a list of active opers
1046     */
1047     static void
1048     stats_operedup(struct Client *source_p)
1049     {
1050     dlink_node *ptr;
1051    
1052     DLINK_FOREACH(ptr, oper_list.head)
1053     {
1054     const struct Client *target_p = ptr->data;
1055    
1056     if (IsOperHidden(target_p) && !IsOper(source_p))
1057     continue;
1058    
1059     if (MyClient(source_p) && IsOper(source_p))
1060     sendto_one(source_p, ":%s %d %s p :[%c][%s] %s (%s@%s) Idle: %d",
1061     from, RPL_STATSDEBUG, to,
1062     IsAdmin(target_p) ?
1063     (IsOperHiddenAdmin(target_p) ? 'O' : 'A') : 'O',
1064     oper_privs_as_string(target_p->localClient->operflags),
1065     target_p->name, target_p->username, target_p->host,
1066     (int)(CurrentTime - target_p->localClient->last));
1067     else
1068     sendto_one(source_p, ":%s %d %s p :[%c] %s (%s@%s) Idle: %d",
1069     from, RPL_STATSDEBUG, to,
1070     IsAdmin(target_p) ?
1071     (IsOperHiddenAdmin(target_p) ? 'O' : 'A') : 'O',
1072     target_p->name, target_p->username, target_p->host,
1073     (int)(CurrentTime - target_p->localClient->last));
1074     }
1075    
1076     sendto_one(source_p, ":%s %d %s p :%lu OPER(s)",
1077     from, RPL_STATSDEBUG, to, dlink_list_length(&oper_list));
1078     }
1079    
1080     static void
1081     stats_ports(struct Client *source_p)
1082     {
1083     if (!IsOper(source_p) && ConfigFileEntry.stats_P_oper_only)
1084     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1085     from, to);
1086     else
1087     show_ports(source_p);
1088     }
1089    
1090     static void
1091     stats_resv(struct Client *source_p)
1092     {
1093     report_resv(source_p);
1094     }
1095    
1096     static void
1097     stats_usage(struct Client *source_p)
1098     {
1099     send_usage(source_p);
1100     }
1101    
1102     static void
1103     stats_tstats(struct Client *source_p)
1104     {
1105     tstats(source_p);
1106     }
1107    
1108     static void
1109     stats_uptime(struct Client *source_p)
1110     {
1111     time_t now = CurrentTime - me.since;
1112     sendto_one(source_p, form_str(RPL_STATSUPTIME), from, to,
1113     now/86400, (now/3600)%24, (now/60)%60, now%60);
1114     if (!ConfigFileEntry.disable_remote || IsOper(source_p))
1115     sendto_one(source_p, form_str(RPL_STATSCONN), from, to,
1116     MaxConnectionCount, MaxClientCount, Count.totalrestartcount);
1117     }
1118    
1119     static void
1120     stats_shared(struct Client *source_p)
1121     {
1122     report_confitem_types(source_p, ULINE_TYPE, 0);
1123     }
1124    
1125     /* stats_servers()
1126     *
1127     * input - client pointer
1128     * output - none
1129     * side effects - client is shown lists of who connected servers
1130     */
1131     static void
1132     stats_servers(struct Client *source_p)
1133     {
1134     struct Client *target_p;
1135     dlink_node *ptr;
1136     int j = 0;
1137    
1138     DLINK_FOREACH(ptr, serv_list.head)
1139     {
1140     target_p = ptr->data;
1141    
1142     j++;
1143    
1144     sendto_one(source_p, ":%s %d %s v :%s (%s!%s@%s) Idle: %d",
1145     from, RPL_STATSDEBUG, to,
1146     target_p->name,
1147     (target_p->serv->by[0] ? target_p->serv->by : "Remote."),
1148     "*", "*", (int)(CurrentTime - target_p->lasttime));
1149     }
1150    
1151     sendto_one(source_p, ":%s %d %s v :%d Server(s)",
1152     from, RPL_STATSDEBUG, to, j);
1153     }
1154    
1155     static void
1156     stats_gecos(struct Client *source_p)
1157     {
1158     report_confitem_types(source_p, XLINE_TYPE, 0);
1159     report_confitem_types(source_p, RXLINE_TYPE, 0);
1160     }
1161    
1162     static void
1163     stats_class(struct Client *source_p)
1164     {
1165     report_confitem_types(source_p, CLASS_TYPE, 0);
1166     }
1167    
1168     static void
1169     stats_memory(struct Client *source_p)
1170     {
1171     count_memory(source_p);
1172     }
1173    
1174     static void
1175     stats_ziplinks(struct Client *source_p)
1176     {
1177     dlink_node *ptr;
1178     struct Client *target_p;
1179     unsigned int sent_data = 0;
1180    
1181     DLINK_FOREACH(ptr, serv_list.head)
1182     {
1183     target_p = ptr->data;
1184    
1185     if (IsCapable(target_p, CAP_ZIP))
1186     {
1187     /* we use memcpy(3) and a local copy of the structure to
1188     * work around a register use bug on GCC on the SPARC.
1189     * -jmallett, 04/27/2002
1190     */
1191     struct ZipStats zipstats;
1192     memcpy(&zipstats, &target_p->localClient->zipstats, sizeof (struct ZipStats));
1193    
1194     sendto_one(source_p, ":%s %d %s Z :ZipLinks stats for %s send[%.2f%% "
1195     "compression (%lu bytes data/%lu bytes wire)] recv[%.2f%% "
1196     "compression (%lu bytes data/%lu bytes wire)]",
1197     from, RPL_STATSDEBUG, to, target_p->name,
1198     zipstats.out_ratio, zipstats.out, zipstats.out_wire,
1199     zipstats.in_ratio, zipstats.in, zipstats.in_wire);
1200     ++sent_data;
1201     }
1202     }
1203    
1204     sendto_one(source_p, ":%s %d %s Z :%u ziplink(s)",
1205     from, RPL_STATSDEBUG, to, sent_data);
1206     }
1207    
1208     static void
1209     stats_servlinks(struct Client *source_p)
1210     {
1211     uint64_t sendB = 0, recvB = 0;
1212     time_t uptime = 0;
1213     int j = 0;
1214     struct Client *target_p = NULL;
1215     dlink_node *ptr;
1216    
1217     if (ConfigServerHide.flatten_links && !IsOper(source_p))
1218     {
1219     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1220     from, to);
1221     return;
1222     }
1223    
1224     DLINK_FOREACH(ptr, serv_list.head)
1225     {
1226     target_p = ptr->data;
1227    
1228     ++j;
1229     sendB += target_p->localClient->send.bytes;
1230     recvB += target_p->localClient->recv.bytes;
1231    
1232     /* ":%s 211 %s %s %u %u %llu %u %llu :%u %u %s" */
1233     sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1234     from, to,
1235     get_client_name(target_p, IsAdmin(source_p) ? SHOW_IP : MASK_IP),
1236     dbuf_length(&target_p->localClient->buf_sendq),
1237     target_p->localClient->send.messages,
1238     target_p->localClient->send.bytes >> 10,
1239     target_p->localClient->recv.messages,
1240     target_p->localClient->recv.bytes >> 10,
1241     (unsigned)(CurrentTime - target_p->firsttime),
1242     (CurrentTime > target_p->since) ? (unsigned)(CurrentTime - target_p->since): 0,
1243     IsOper(source_p) ? show_capabilities(target_p) : "TS");
1244     }
1245    
1246     sendB >>= 10;
1247     recvB >>= 10;
1248    
1249     sendto_one(source_p, ":%s %d %s ? :%u total server(s)",
1250     from, RPL_STATSDEBUG, to, j);
1251     sendto_one(source_p, ":%s %d %s ? :Sent total : %7.2f %s",
1252     from, RPL_STATSDEBUG, to,
1253     _GMKv((signed)sendB), _GMKs((signed)sendB));
1254     sendto_one(source_p, ":%s %d %s ? :Recv total : %7.2f %s",
1255     from, RPL_STATSDEBUG, to,
1256     _GMKv((signed)recvB), _GMKs((signed)recvB));
1257    
1258     uptime = (CurrentTime - me.since);
1259    
1260     sendto_one(source_p, ":%s %d %s ? :Server send: %7.2f %s (%4.1f K/s)",
1261     from, RPL_STATSDEBUG, to,
1262     _GMKv((signed)(me.localClient->send.bytes>>10)),
1263     _GMKs((signed)(me.localClient->send.bytes>>10)),
1264     (float)((float)(((signed)me.localClient->send.bytes) >> 10) /
1265     (float)uptime));
1266     sendto_one(source_p, ":%s %d %s ? :Server recv: %7.2f %s (%4.1f K/s)",
1267     from, RPL_STATSDEBUG, to,
1268     _GMKv((signed)(me.localClient->recv.bytes>>10)),
1269     _GMKs((signed)(me.localClient->recv.bytes>>10)),
1270     (float)((float)(((signed)me.localClient->recv.bytes) >> 10) /
1271     (float)uptime));
1272     }
1273    
1274     static void
1275     stats_ltrace(struct Client *source_p, int parc, char *parv[])
1276     {
1277     int doall = 0;
1278     int wilds = 0;
1279     char *name = NULL;
1280     char statchar;
1281    
1282     if ((name = parse_stats_args(parc, parv, &doall, &wilds)) != NULL)
1283     {
1284     statchar = parv[1][0];
1285    
1286     stats_L(source_p, name, doall, wilds, statchar);
1287     }
1288     else
1289     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1290     from, to, "STATS");
1291     }
1292    
1293 adx 65 static void
1294     stats_hooks(struct Client *source_p)
1295     {
1296     dlink_node *ptr;
1297     struct Callback *cb;
1298     char lastused[32];
1299    
1300     sendto_one(source_p, ":%s %d %s : %-20s %-20s Used Hooks", me.name,
1301     RPL_STATSDEBUG, source_p->name, "Callback", "Last Execution");
1302     sendto_one(source_p, ":%s %d %s : ------------------------------------"
1303     "--------------------", me.name, RPL_STATSDEBUG, source_p->name);
1304    
1305     DLINK_FOREACH(ptr, callback_list.head)
1306     {
1307     cb = ptr->data;
1308    
1309     if (cb->last != 0)
1310     snprintf(lastused, sizeof(lastused), "%d seconds ago",
1311     (int) (CurrentTime - cb->last));
1312     else
1313     strcpy(lastused, "NEVER");
1314    
1315     sendto_one(source_p, ":%s %d %s : %-20s %-20s %-8u %d", me.name,
1316     RPL_STATSDEBUG, source_p->name, cb->name, lastused, cb->called,
1317     dlink_list_length(&cb->chain));
1318     }
1319    
1320     sendto_one(source_p, ":%s %d %s : ", me.name, RPL_STATSDEBUG,
1321     source_p->name);
1322     }
1323    
1324     static void
1325     stats_events(struct Client *source_p)
1326     {
1327     int i;
1328    
1329     if (last_event_ran)
1330     {
1331     sendto_one(source_p, ":%s %d %s :Last event to run: %s",
1332     me.name, RPL_STATSDEBUG, source_p->name, last_event_ran);
1333     sendto_one(source_p, ":%s %d %s : ",
1334     me.name, RPL_STATSDEBUG, source_p->name);
1335     }
1336    
1337     sendto_one(source_p,
1338     ":%s %d %s : Operation Next Execution",
1339     me.name, RPL_STATSDEBUG, source_p->name);
1340     sendto_one(source_p,
1341     ":%s %d %s : -------------------------------------------",
1342     me.name, RPL_STATSDEBUG, source_p->name);
1343    
1344     for (i = 0; i < MAX_EVENTS; i++)
1345     if (event_table[i].active)
1346     {
1347     sendto_one(source_p, ":%s %d %s : %-28s %-4d seconds",
1348     me.name, RPL_STATSDEBUG, source_p->name,
1349     event_table[i].name,
1350     (int)(event_table[i].when - CurrentTime));
1351     }
1352    
1353     sendto_one(source_p, ":%s %d %s : ",
1354     me.name, RPL_STATSDEBUG, source_p->name);
1355     }
1356    
1357 adx 67 static void
1358     stats_dns_servers(struct Client *source_p)
1359     {
1360     int i;
1361     char ipaddr[HOSTIPLEN];
1362    
1363     for (i = 0; i < irc_nscount; i++)
1364     {
1365     irc_getnameinfo((struct sockaddr *)&(irc_nsaddr_list[i]),
1366     irc_nsaddr_list[i].ss_len, ipaddr, HOSTIPLEN, NULL, 0,
1367     NI_NUMERICHOST);
1368     sendto_one(source_p, form_str(RPL_STATSALINE),
1369     me.name, source_p->name, ipaddr);
1370     }
1371     }
1372    
1373 adx 68 static void
1374     fd_dump(struct Client *source_p)
1375     {
1376     int i;
1377     fde_t *F;
1378    
1379     for (i = 0; i < FD_HASH_SIZE; i++)
1380     for (F = fd_hash[i]; F != NULL; F = F->hnext)
1381     sendto_one(source_p, ":%s %d %s :fd %-5d desc '%s'",
1382     me.name, RPL_STATSDEBUG, source_p->name,
1383     F->fd, F->desc);
1384     }
1385    
1386 adx 30 /*
1387     * ms_stats - STATS message handler
1388     * parv[0] = sender prefix
1389     * parv[1] = statistics selector (defaults to Message frequency)
1390     * parv[2] = server name (current server defaulted, if omitted)
1391     */
1392     static void
1393     ms_stats(struct Client *client_p, struct Client *source_p,
1394     int parc, char *parv[])
1395     {
1396     if (hunt_server(client_p,source_p,":%s STATS %s :%s",2,parc,parv)!=HUNTED_ISME)
1397     return;
1398    
1399     if (IsClient(source_p))
1400     mo_stats(client_p, source_p, parc, parv);
1401     }
1402    
1403     /*
1404     * stats_L
1405     *
1406     * inputs - pointer to client to report to
1407     * - doall flag
1408     * - wild card or not
1409     * output - NONE
1410     * side effects -
1411     */
1412     static void
1413     stats_L(struct Client *source_p,char *name,int doall,
1414     int wilds,char statchar)
1415     {
1416     stats_L_list(source_p, name, doall, wilds, &unknown_list, statchar);
1417     stats_L_list(source_p, name, doall, wilds, &local_client_list, statchar);
1418     stats_L_list(source_p, name, doall, wilds, &serv_list, statchar);
1419     }
1420    
1421     static void
1422     stats_L_list(struct Client *source_p,char *name, int doall, int wilds,
1423     dlink_list *list,char statchar)
1424     {
1425     dlink_node *ptr;
1426     struct Client *target_p;
1427    
1428     /*
1429     * send info about connections which match, or all if the
1430     * mask matches from. Only restrictions are on those who
1431     * are invisible not being visible to 'foreigners' who use
1432     * a wild card based search to list it.
1433     */
1434     DLINK_FOREACH(ptr, list->head)
1435     {
1436     target_p = ptr->data;
1437    
1438     if (IsInvisible(target_p) && (doall || wilds) &&
1439     !(MyConnect(source_p) && IsOper(source_p)) &&
1440     !IsOper(target_p) && (target_p != source_p))
1441     continue;
1442     if (!doall && wilds && !match(name, target_p->name))
1443     continue;
1444     if (!(doall || wilds) && irccmp(name, target_p->name))
1445     continue;
1446    
1447     /* This basically shows ips for our opers if its not a server/admin, or
1448     * its one of our admins. */
1449     if(MyClient(source_p) && IsOper(source_p) &&
1450     (IsAdmin(source_p) ||
1451     (!IsServer(target_p) && !IsAdmin(target_p) &&
1452     !IsHandshake(target_p) && !IsConnecting(target_p))))
1453     {
1454     sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1455     from, to,
1456     (IsUpper(statchar)) ?
1457     get_client_name(target_p, SHOW_IP) :
1458     get_client_name(target_p, HIDE_IP),
1459     dbuf_length(&target_p->localClient->buf_sendq),
1460     target_p->localClient->send.messages,
1461     target_p->localClient->send.bytes>>10,
1462     target_p->localClient->recv.messages,
1463     target_p->localClient->recv.bytes>>10,
1464     (unsigned)(CurrentTime - target_p->firsttime),
1465     (CurrentTime > target_p->since) ? (unsigned)(CurrentTime - target_p->since):0,
1466     IsServer(target_p) ? show_capabilities(target_p) : "-");
1467     }
1468     else
1469     {
1470     /* If its a hidden ip, an admin, or a server, mask the real IP */
1471     if(IsIPSpoof(target_p) || IsServer(target_p) || IsAdmin(target_p)
1472     || IsHandshake(target_p) || IsConnecting(target_p))
1473     sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1474     from, to,
1475     get_client_name(target_p, MASK_IP),
1476     dbuf_length(&target_p->localClient->buf_sendq),
1477     target_p->localClient->send.messages,
1478     target_p->localClient->send.bytes>>10,
1479     target_p->localClient->recv.messages,
1480     target_p->localClient->recv.bytes>>10,
1481     (unsigned)(CurrentTime - target_p->firsttime),
1482     (CurrentTime > target_p->since) ? (unsigned)(CurrentTime - target_p->since):0,
1483     IsServer(target_p) ? show_capabilities(target_p) : "-");
1484     else /* show the real IP */
1485     sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1486     from, to,
1487     (IsUpper(statchar)) ?
1488     get_client_name(target_p, SHOW_IP) :
1489     get_client_name(target_p, HIDE_IP),
1490     dbuf_length(&target_p->localClient->buf_sendq),
1491     target_p->localClient->send.messages,
1492     target_p->localClient->send.bytes>>10,
1493     target_p->localClient->recv.messages,
1494     target_p->localClient->recv.bytes>>10,
1495     (unsigned)(CurrentTime - target_p->firsttime),
1496     (CurrentTime > target_p->since) ? (unsigned)(CurrentTime - target_p->since):0,
1497     IsServer(target_p) ? show_capabilities(target_p) : "-");
1498     }
1499     }
1500     }
1501    
1502     /* parse_stats_args()
1503     *
1504     * inputs - arg count
1505     * - args
1506     * - doall flag
1507     * - wild card or not
1508     * output - pointer to name to use
1509     * side effects -
1510     * common parse routine for m_stats args
1511     *
1512     */
1513     static char *
1514     parse_stats_args(int parc, char *parv[], int *doall, int *wilds)
1515     {
1516     char *name;
1517    
1518     if (parc > 2)
1519     {
1520     name = parv[2];
1521    
1522     if (!irccmp(name, from))
1523     *doall = 2;
1524     else if (match(name, from))
1525     *doall = 1;
1526    
1527     if (strchr(name, '*') ||
1528     strchr(name, '?'))
1529     *wilds = 1;
1530    
1531     return(name);
1532     }
1533     else
1534     return(NULL);
1535     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision