ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_stats.c
Revision: 7330
Committed: Fri Feb 19 17:50:13 2016 UTC (8 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 50098 byte(s)
Log Message:
- Now that we got time_t to work nicely on openbsd with snprintf's conversion specifiers,
  we ran into a similiar issue on Raspbian/ARMv7's time_t which is of signed 32 bit and
  doesn't cope at all with %j. Instead of doing tricks, get rid of time_t everywhere and
  forever and use uintmax_t instead which has at least a 'standardized' conversion specifier
  associated with it.

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2820 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 7006 * Copyright (c) 1997-2016 ircd-hybrid development team
5 adx 30 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * USA
20     */
21    
22 michael 2820 /*! \file m_stats.c
23     * \brief Includes required functions for processing the STATS command.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28 michael 2820 #include "list.h"
29     #include "client.h"
30     #include "irc_string.h"
31     #include "ircd.h"
32     #include "listener.h"
33 michael 1632 #include "conf.h"
34 michael 1644 #include "conf_class.h"
35 michael 7209 #include "conf_cluster.h"
36 michael 7304 #include "conf_gecos.h"
37 michael 7234 #include "conf_resv.h"
38 michael 7248 #include "conf_service.h"
39 michael 7209 #include "conf_shared.h"
40 adx 30 #include "hostmask.h"
41 michael 2820 #include "numeric.h"
42     #include "send.h"
43     #include "fdlist.h"
44 michael 3347 #include "misc.h"
45     #include "server.h"
46     #include "user.h"
47 michael 2820 #include "event.h"
48 adx 30 #include "dbuf.h"
49     #include "parse.h"
50     #include "modules.h"
51     #include "whowas.h"
52 michael 884 #include "watch.h"
53 michael 6836 #include "reslib.h"
54 michael 2150 #include "motd.h"
55 michael 4325 #include "ipcache.h"
56 adx 30
57    
58 michael 7209 static void
59     report_shared(struct Client *source_p)
60 michael 1922 {
61 michael 7218 static const struct shared_types
62 michael 7209 {
63     unsigned int type;
64     unsigned char letter;
65     } flag_table[] = {
66     { SHARED_KLINE, 'K' },
67     { SHARED_UNKLINE, 'U' },
68     { SHARED_XLINE, 'X' },
69     { SHARED_UNXLINE, 'Y' },
70     { SHARED_RESV, 'Q' },
71     { SHARED_UNRESV, 'R' },
72     { SHARED_LOCOPS, 'L' },
73     { SHARED_DLINE, 'D' },
74     { SHARED_UNDLINE, 'E' },
75     { 0, '\0' }
76     };
77 michael 1922
78 michael 7209 dlink_node *node;
79 michael 7218 char buf[sizeof(flag_table) / sizeof(struct shared_types)];
80 michael 7209
81     DLINK_FOREACH(node, shared_get_list()->head)
82     {
83 michael 7218 const struct SharedItem *shared = node->data;
84 michael 7209 char *p = buf;
85    
86     *p++ = 'c';
87    
88 michael 7218 for (const struct shared_types *tab = flag_table; tab->type; ++tab)
89     if (tab->type & shared->type)
90     *p++ = tab->letter;
91 michael 7209 else
92 michael 7218 *p++ = ToLower(tab->letter);
93 michael 7209
94     *p = '\0';
95    
96 michael 7218 sendto_one_numeric(source_p, &me, RPL_STATSULINE, shared->server,
97     shared->user, shared->host, buf);
98 michael 7209 }
99     }
100    
101     static void
102     report_cluster(struct Client *source_p)
103     {
104 michael 7218 static const struct cluster_types
105 michael 7209 {
106     unsigned int type;
107     unsigned char letter;
108     } flag_table[] = {
109     { CLUSTER_KLINE, 'K' },
110     { CLUSTER_UNKLINE, 'U' },
111     { CLUSTER_XLINE, 'X' },
112     { CLUSTER_UNXLINE, 'Y' },
113     { CLUSTER_RESV, 'Q' },
114     { CLUSTER_UNRESV, 'R' },
115     { CLUSTER_LOCOPS, 'L' },
116     { CLUSTER_DLINE, 'D' },
117     { CLUSTER_UNDLINE, 'E' },
118     { 0, '\0' }
119     };
120    
121     dlink_node *node;
122 michael 7218 char buf[sizeof(flag_table) / sizeof(struct cluster_types)];
123 michael 7209
124     DLINK_FOREACH(node, cluster_get_list()->head)
125     {
126 michael 7218 const struct ClusterItem *cluster = node->data;
127 michael 7209 char *p = buf;
128    
129     *p++ = 'C';
130    
131 michael 7218 for (const struct cluster_types *tab = flag_table; tab->type; ++tab)
132     if (tab->type & cluster->type)
133     *p++ = tab->letter;
134 michael 7209 else
135 michael 7218 *p++ = ToLower(tab->letter);
136 michael 7209
137     *p = '\0';
138    
139 michael 7218 sendto_one_numeric(source_p, &me, RPL_STATSULINE, cluster->server,
140 michael 7209 "*", "*", buf);
141     }
142     }
143    
144 michael 7248 static void
145     report_service(struct Client *source_p)
146     {
147     dlink_node *node;
148    
149     DLINK_FOREACH(node, service_get_list()->head)
150     {
151     const struct ServiceItem *service = node->data;
152     sendto_one_numeric(source_p, &me, RPL_STATSSERVICE, 'S', "*", service->name, 0, 0);
153     }
154     }
155    
156 michael 7304 static void
157     report_gecos(struct Client *source_p)
158     {
159     dlink_node *node;
160    
161     DLINK_FOREACH(node, gecos_get_list()->head)
162     {
163     const struct GecosItem *gecos = node->data;
164     sendto_one_numeric(source_p, &me, RPL_STATSXLINE,
165 michael 7313 gecos->expire ? 'x' : 'X',
166 michael 7304 gecos->mask, gecos->reason);
167     }
168     }
169    
170 adx 30 /*
171 michael 1922 * inputs - pointer to client requesting confitem report
172     * - ConfType to report
173     * output - none
174     * side effects -
175     */
176     static void
177     report_confitem_types(struct Client *source_p, enum maskitem_type type)
178     {
179 michael 4815 const dlink_node *node = NULL;
180 michael 4032 const struct MaskItem *conf = NULL;
181 michael 2691 char buf[IRCD_BUFSIZE];
182 michael 1922 char *p = NULL;
183    
184     switch (type)
185     {
186 michael 4034 case CONF_OPER:
187 michael 6628 DLINK_FOREACH(node, operator_items.head)
188 michael 4034 {
189 michael 4815 conf = node->data;
190 michael 1922
191 michael 4034 /* Don't allow non opers to see oper privs */
192     if (HasUMode(source_p, UMODE_OPER))
193     sendto_one_numeric(source_p, &me, RPL_STATSOLINE, 'O', conf->user, conf->host,
194     conf->name, oper_privs_as_string(conf->port),
195     conf->class->name);
196     else
197     sendto_one_numeric(source_p, &me, RPL_STATSOLINE, 'O', conf->user, conf->host,
198     conf->name, "0", conf->class->name);
199     }
200 michael 1922
201 michael 4034 break;
202 michael 1922
203 michael 4034 case CONF_SERVER:
204 michael 4815 DLINK_FOREACH(node, server_items.head)
205 michael 4034 {
206     p = buf;
207 michael 4815 conf = node->data;
208 michael 1922
209 michael 4034 buf[0] = '\0';
210 michael 1922
211 michael 4034 if (IsConfAllowAutoConn(conf))
212     *p++ = 'A';
213     if (IsConfSSL(conf))
214     *p++ = 'S';
215     if (buf[0] == '\0')
216     *p++ = '*';
217    
218     *p = '\0';
219    
220     /*
221     * Allow admins to see actual ips unless hide_server_ips is enabled
222     */
223     if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
224     sendto_one_numeric(source_p, &me, RPL_STATSCLINE, 'C', conf->host,
225     buf, conf->name, conf->port,
226     conf->class->name);
227 michael 1922 else
228 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSCLINE, 'C',
229 michael 4034 "*@127.0.0.1", buf, conf->name, conf->port,
230     conf->class->name);
231     }
232 michael 1922
233 michael 4034 break;
234    
235     default:
236     break;
237 michael 1922 }
238     }
239    
240 michael 1927 /* report_resv()
241     *
242     * inputs - pointer to client pointer to report to.
243     * output - NONE
244     * side effects - report all resvs to client.
245     */
246     static void
247     report_resv(struct Client *source_p)
248     {
249 michael 4815 const dlink_node *node = NULL;
250 michael 1927
251 michael 7282 DLINK_FOREACH(node, resv_chan_get_list()->head)
252 michael 1927 {
253 michael 7282 const struct ResvItem *resv = node->data;
254 michael 3109
255     sendto_one_numeric(source_p, &me, RPL_STATSQLINE,
256 michael 7282 resv->expire ? 'q' : 'Q',
257     resv->mask, resv->reason);
258 michael 1927 }
259    
260 michael 7282 DLINK_FOREACH(node, resv_nick_get_list()->head)
261 michael 1927 {
262 michael 7282 const struct ResvItem *resv = node->data;
263 michael 3109
264     sendto_one_numeric(source_p, &me, RPL_STATSQLINE,
265 michael 7282 resv->expire ? 'q' : 'Q',
266     resv->mask, resv->reason);
267 michael 1927 }
268     }
269    
270 michael 1922 /*
271 adx 30 * This is part of the STATS replies. There is no offical numeric for this
272 michael 4298 * since this isn't an official command, in much the same way as HASH isn't.
273 adx 30 * It is also possible that some systems wont support this call or have
274     * different field names for "struct rusage".
275     * -avalon
276     */
277     static void
278 michael 1457 stats_usage(struct Client *source_p, int parc, char *parv[])
279 adx 30 {
280     struct rusage rus;
281 michael 7330 uintmax_t secs;
282     uintmax_t rup;
283 adx 30 #ifdef hz
284     # define hzz hz
285     #else
286     # ifdef HZ
287     # define hzz HZ
288     # else
289     int hzz = 1;
290     # endif
291     #endif
292    
293     if (getrusage(RUSAGE_SELF, &rus) == -1)
294     {
295 michael 3110 sendto_one_notice(source_p, &me, ":Getruseage error: %s",
296     strerror(errno));
297 adx 30 return;
298     }
299    
300     secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec;
301    
302     if (secs == 0)
303     secs = 1;
304    
305 michael 4588 rup = (CurrentTime - me.connection->since) * hzz;
306 adx 30
307     if (rup == 0)
308     rup = 1;
309    
310 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
311 michael 3573 "R :CPU Secs %d:%02d User %d:%02d System %d:%02d",
312     (int)(secs/60), (int)(secs%60),
313     (int)(rus.ru_utime.tv_sec/60), (int)(rus.ru_utime.tv_sec%60),
314     (int)(rus.ru_stime.tv_sec/60), (int)(rus.ru_stime.tv_sec%60));
315 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
316 michael 7330 "R :RSS %ld ShMem %ju Data %ju Stack %ju",
317 michael 3573 rus.ru_maxrss,
318 michael 7330 (uintmax_t)(rus.ru_ixrss / rup), (uintmax_t)(rus.ru_idrss / rup),
319     (uintmax_t)(rus.ru_isrss / rup));
320 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
321 michael 3573 "R :Swaps %d Reclaims %d Faults %d",
322     (int)rus.ru_nswap,
323     (int)rus.ru_minflt, (int)rus.ru_majflt);
324 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
325 michael 3573 "R :Block in %d out %d",
326     (int)rus.ru_inblock,
327     (int)rus.ru_oublock);
328 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
329 michael 3573 "R :Msg Rcv %d Send %d",
330     (int)rus.ru_msgrcv,
331     (int)rus.ru_msgsnd);
332 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
333 michael 3573 "R :Signals %d Context Vol. %d Invol %d",
334     (int)rus.ru_nsignals,
335     (int)rus.ru_nvcsw, (int)rus.ru_nivcsw);
336 adx 30 }
337    
338     static void
339 michael 1457 stats_memory(struct Client *source_p, int parc, char *parv[])
340 adx 30 {
341     const dlink_node *gptr = NULL;
342     const dlink_node *dlink = NULL;
343    
344 michael 948 unsigned int local_client_conf_count = 0; /* local client conf links */
345     unsigned int users_counted = 0; /* user structs */
346 adx 30
347 michael 1017 unsigned int channel_members = 0;
348 michael 948 unsigned int channel_invites = 0;
349     unsigned int channel_bans = 0;
350     unsigned int channel_except = 0;
351     unsigned int channel_invex = 0;
352 adx 30
353 michael 948 unsigned int wwu = 0; /* whowas users */
354     unsigned int class_count = 0; /* classes */
355     unsigned int aways_counted = 0;
356 michael 4329 unsigned int number_ips_stored = 0; /* number of ip addresses hashed */
357 adx 30
358 michael 6719 size_t channel_memory = 0;
359     size_t channel_ban_memory = 0;
360     size_t channel_except_memory = 0;
361     size_t channel_invex_memory = 0;
362 adx 30
363     unsigned int safelist_count = 0;
364 michael 6719 size_t safelist_memory = 0;
365 adx 30
366 michael 6719 size_t wwm = 0; /* whowas array memory used */
367     size_t conf_memory = 0; /* memory used by conf lines */
368     size_t mem_ips_stored = 0; /* memory used by ip address hash */
369 adx 30
370 michael 6719 size_t total_channel_memory = 0;
371     size_t totww = 0;
372 adx 30
373     unsigned int local_client_count = 0;
374     unsigned int remote_client_count = 0;
375    
376 michael 6719 size_t local_client_memory_used = 0;
377     size_t remote_client_memory_used = 0;
378 adx 30
379 michael 6719 size_t total_memory = 0;
380 michael 6932 unsigned int channel_topics = 0;
381 adx 30
382 michael 1017 unsigned int watch_list_headers = 0; /* watchlist headers */
383     unsigned int watch_list_entries = 0; /* watchlist entries */
384 michael 6719 size_t watch_list_memory = 0; /* watchlist memory used */
385 michael 884
386 adx 30
387     DLINK_FOREACH(gptr, global_client_list.head)
388     {
389 michael 4032 const struct Client *target_p = gptr->data;
390 adx 30
391     if (MyConnect(target_p))
392     {
393     ++local_client_count;
394 michael 4588 local_client_conf_count += dlink_list_length(&target_p->connection->confs);
395     watch_list_entries += dlink_list_length(&target_p->connection->watches);
396 adx 30 }
397     else
398     ++remote_client_count;
399    
400     if (IsClient(target_p))
401     {
402     ++users_counted;
403    
404 michael 1483 if (target_p->away[0])
405 adx 30 ++aways_counted;
406     }
407     }
408    
409     /* Count up all channels, ban lists, except lists, Invex lists */
410 michael 5757 channel_memory = dlink_list_length(&channel_list) * sizeof(struct Channel);
411    
412 michael 3944 DLINK_FOREACH(gptr, channel_list.head)
413 adx 30 {
414 michael 948 const struct Channel *chptr = gptr->data;
415 adx 30
416 michael 1017 channel_members += dlink_list_length(&chptr->members);
417 adx 30 channel_invites += dlink_list_length(&chptr->invites);
418    
419 michael 1203 if (chptr->topic[0])
420 michael 6932 ++channel_topics;
421 adx 30
422 michael 1017 channel_bans += dlink_list_length(&chptr->banlist);
423     channel_ban_memory += dlink_list_length(&chptr->banlist) * sizeof(struct Ban);
424    
425     channel_except += dlink_list_length(&chptr->exceptlist);
426     channel_except_memory += dlink_list_length(&chptr->exceptlist) * sizeof(struct Ban);
427    
428     channel_invex += dlink_list_length(&chptr->invexlist);
429     channel_invex_memory += dlink_list_length(&chptr->invexlist) * sizeof(struct Ban);
430 adx 30 }
431    
432     if ((safelist_count = dlink_list_length(&listing_client_list)))
433     {
434     safelist_memory = safelist_count * sizeof(struct ListTask);
435     DLINK_FOREACH(gptr, listing_client_list.head)
436     {
437 michael 948 const struct Client *acptr = gptr->data;
438 adx 30
439 michael 4588 DLINK_FOREACH(dlink, acptr->connection->list_task->show_mask.head)
440 adx 30 safelist_memory += strlen(dlink->data);
441    
442 michael 4588 DLINK_FOREACH(dlink, acptr->connection->list_task->hide_mask.head)
443 adx 30 safelist_memory += strlen(dlink->data);
444     }
445     }
446    
447     #if 0
448     /* XXX THIS has to be fixed !!!! -db */
449     /* count up all config items */
450     DLINK_FOREACH(dlink, ConfigItemList.head)
451     {
452     aconf = dlink->data;
453     conf_memory += aconf->host ? strlen(aconf->host)+1 : 0;
454     conf_memory += aconf->passwd ? strlen(aconf->passwd)+1 : 0;
455     conf_memory += aconf->name ? strlen(aconf->name)+1 : 0;
456     conf_memory += sizeof(struct AccessItem);
457     }
458     #endif
459     /* count up all classes */
460 michael 1644 class_count = dlink_list_length(class_get_list());
461 adx 30
462 michael 2297 whowas_count_memory(&wwu, &wwm);
463 michael 1017 watch_count_memory(&watch_list_headers, &watch_list_memory);
464 michael 884
465 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
466 michael 6782 "z :WATCH headers %u(%zu) entries %d(%u)",
467 michael 3573 watch_list_headers,
468     watch_list_memory, watch_list_entries,
469     watch_list_entries * sizeof(dlink_node) * 2);
470 michael 884
471 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
472 michael 3573 "z :Clients %u(%u)",
473     users_counted,
474     (users_counted * sizeof(struct Client)));
475 adx 30
476 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
477 michael 3573 "z :User aways %u", aways_counted);
478 adx 30
479 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
480 michael 6719 "z :Attached confs %u(%zu)",
481 michael 3573 local_client_conf_count,
482 michael 6719 local_client_conf_count * sizeof(dlink_node));
483 adx 30
484 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
485 michael 6719 "z :Resv channels %u(%zu) nicks %u(%zu)",
486 michael 7282 dlink_list_length(resv_chan_get_list()),
487     dlink_list_length(resv_chan_get_list()) * sizeof(struct ResvItem),
488     dlink_list_length(resv_nick_get_list()),
489     dlink_list_length(resv_nick_get_list()) * sizeof(struct ResvItem));
490 adx 30
491 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
492 michael 6719 "z :Classes %u(%zu)",
493     class_count, class_count * sizeof(struct ClassItem));
494 adx 30
495 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
496 michael 6932 "z :Channels %u(%zu) Topics %u",
497 michael 3944 dlink_list_length(&channel_list),
498 michael 6932 channel_memory, channel_topics);
499 adx 30
500 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
501 michael 6719 "z :Bans %u(%zu)",
502 michael 3573 channel_bans, channel_ban_memory);
503 adx 30
504 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
505 michael 6719 "z :Exceptions %u(%zu)",
506 michael 3573 channel_except, channel_except_memory);
507 adx 30
508 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
509 michael 6719 "z :Invex %u(%zu)",
510 michael 3573 channel_invex, channel_invex_memory);
511 adx 30
512 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
513 michael 6719 "z :Channel members %u(%zu) invites %u(%zu)",
514 michael 3573 channel_members,
515 michael 6719 channel_members * sizeof(struct Membership),
516     channel_invites,
517     channel_invites * sizeof(dlink_node) * 2);
518 adx 30
519     total_channel_memory = channel_memory + channel_ban_memory +
520 michael 1017 channel_members * sizeof(struct Membership) +
521 michael 6719 (channel_invites * sizeof(dlink_node) * 2);
522 adx 30
523 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
524 michael 6719 "z :Safelist %u(%zu)",
525 michael 3573 safelist_count, safelist_memory);
526 adx 30
527 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
528 michael 6719 "z :Whowas users %u(%zu)",
529     wwu, wwu * sizeof(struct Client));
530 adx 30
531 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
532 michael 6719 "z :Whowas array %u(%zu)",
533 michael 3573 NICKNAMEHISTORYLENGTH, wwm);
534 adx 30
535     totww = wwu * sizeof(struct Client) + wwm;
536    
537 michael 2150 motd_memory_count(source_p);
538 michael 4325 ipcache_get_stats(&number_ips_stored, &mem_ips_stored);
539 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
540 michael 6719 "z :iphash %u(%zu)",
541 michael 3573 number_ips_stored, mem_ips_stored);
542 adx 30
543     total_memory = totww + total_channel_memory + conf_memory + class_count *
544     sizeof(struct ClassItem);
545 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
546 michael 6719 "z :Total: whowas %zu channel %zu conf %zu",
547 michael 3573 totww, total_channel_memory, conf_memory);
548 adx 30
549 michael 4576 local_client_memory_used = local_client_count*(sizeof(struct Client) + sizeof(struct Connection));
550 adx 30 total_memory += local_client_memory_used;
551 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
552 michael 6719 "z :Local client Memory in use: %u(%zu)",
553 michael 3573 local_client_count, local_client_memory_used);
554 adx 30
555     remote_client_memory_used = remote_client_count * sizeof(struct Client);
556     total_memory += remote_client_memory_used;
557 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
558 michael 6719 "z :Remote client Memory in use: %u(%zu)",
559 michael 3573 remote_client_count, remote_client_memory_used);
560 adx 30
561 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
562 michael 6719 "z :TOTAL: %zu",
563 michael 3573 me.name, RPL_STATSDEBUG, source_p->name,
564     total_memory);
565 adx 30 }
566    
567     static void
568 michael 4479 stats_dns_servers(struct Client *source_p, int parc, char *parv[])
569 adx 30 {
570 michael 6836 char ipaddr[HOSTIPLEN + 1] = "";
571    
572     for (unsigned int i = 0; i < irc_nscount; ++i)
573     {
574     getnameinfo((const struct sockaddr *)&(irc_nsaddr_list[i]),
575     irc_nsaddr_list[i].ss_len, ipaddr,
576     sizeof(ipaddr), NULL, 0, NI_NUMERICHOST);
577     sendto_one_numeric(source_p, &me, RPL_STATSALINE, ipaddr);
578 michael 6990 }
579 adx 30 }
580    
581     static void
582 michael 1457 stats_connect(struct Client *source_p, int parc, char *parv[])
583 adx 30 {
584 michael 1632 report_confitem_types(source_p, CONF_SERVER);
585 adx 30 }
586    
587     /* stats_deny()
588     *
589     * input - client to report to
590     * output - none
591     * side effects - client is given dline list.
592     */
593     static void
594 michael 1457 stats_deny(struct Client *source_p, int parc, char *parv[])
595 adx 30 {
596 michael 4032 const struct MaskItem *conf = NULL;
597 michael 4815 const dlink_node *node = NULL;
598 adx 30
599 michael 3246 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
600 adx 30 {
601 michael 4815 DLINK_FOREACH(node, atable[i].head)
602 adx 30 {
603 michael 4815 const struct AddressRec *arec = node->data;
604 michael 1367
605 michael 1632 if (arec->type != CONF_DLINE)
606     continue;
607 adx 30
608 michael 1632 conf = arec->conf;
609 adx 30
610 michael 5542 /* Don't report a temporary dline as permanent dline */
611 michael 1649 if (conf->until)
612 michael 1632 continue;
613 adx 30
614 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSDLINE, 'D', conf->host, conf->reason);
615 adx 30 }
616     }
617     }
618    
619     /* stats_tdeny()
620     *
621     * input - client to report to
622     * output - none
623     * side effects - client is given dline list.
624     */
625     static void
626 michael 1457 stats_tdeny(struct Client *source_p, int parc, char *parv[])
627 adx 30 {
628 michael 4032 const struct MaskItem *conf = NULL;
629 michael 4815 const dlink_node *node = NULL;
630 adx 30
631 michael 3246 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
632 adx 30 {
633 michael 4815 DLINK_FOREACH(node, atable[i].head)
634 adx 30 {
635 michael 4815 const struct AddressRec *arec = node->data;
636 michael 1367
637 michael 1632 if (arec->type != CONF_DLINE)
638     continue;
639 adx 30
640 michael 1632 conf = arec->conf;
641 adx 30
642 michael 5542 /* Don't report a permanent dline as temporary dline */
643 michael 1649 if (!conf->until)
644 michael 1632 continue;
645 adx 30
646 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSDLINE, 'd', conf->host, conf->reason);
647 adx 30 }
648     }
649     }
650    
651     /* stats_exempt()
652     *
653     * input - client to report to
654     * output - none
655     * side effects - client is given list of exempt blocks
656     */
657     static void
658 michael 1457 stats_exempt(struct Client *source_p, int parc, char *parv[])
659 adx 30 {
660 michael 4034 const struct MaskItem *conf = NULL;
661 michael 4815 const dlink_node *node = NULL;
662 adx 30
663 michael 4340 if (ConfigGeneral.stats_e_disabled)
664 michael 584 {
665 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
666 michael 584 return;
667     }
668    
669 michael 3246 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
670 adx 30 {
671 michael 4815 DLINK_FOREACH(node, atable[i].head)
672 adx 30 {
673 michael 4815 const struct AddressRec *arec = node->data;
674 michael 1367
675 michael 1632 if (arec->type != CONF_EXEMPT)
676     continue;
677 adx 30
678 michael 1632 conf = arec->conf;
679 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSDLINE, 'e', conf->host, "");
680 adx 30 }
681     }
682     }
683    
684     static void
685 michael 1457 stats_events(struct Client *source_p, int parc, char *parv[])
686 adx 30 {
687 michael 6306 const dlink_node *node;
688    
689     sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
690     "E :Operation Next Execution");
691     sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
692     "E :---------------------------------------------");
693    
694     DLINK_FOREACH(node, event_get_list()->head)
695     {
696     const struct event *ev = node->data;
697    
698     sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
699     "E :%-30s %-4d seconds",
700     ev->name,
701     (int)(ev->next - CurrentTime));
702     }
703 adx 30 }
704    
705     static void
706 michael 1457 stats_hubleaf(struct Client *source_p, int parc, char *parv[])
707 adx 30 {
708 michael 4815 const dlink_node *node = NULL, *dptr = NULL;
709 michael 2118
710 michael 4815 DLINK_FOREACH(node, server_items.head)
711 michael 2118 {
712 michael 4815 const struct MaskItem *conf = node->data;
713 michael 2118
714     DLINK_FOREACH(dptr, conf->hub_list.head)
715 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSHLINE, 'H', dptr->data, conf->name, 0, "*");
716 michael 2118 }
717    
718 michael 4815 DLINK_FOREACH(node, server_items.head)
719 michael 2118 {
720 michael 4815 const struct MaskItem *conf = node->data;
721 michael 2118
722     DLINK_FOREACH(dptr, conf->leaf_list.head)
723 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSLLINE, 'L', dptr->data, conf->name, 0, "*");
724 michael 2118 }
725 adx 30 }
726    
727 michael 1372 /*
728     * show_iline_prefix()
729     *
730     * inputs - pointer to struct Client requesting output
731 michael 2820 * - pointer to struct MaskItem
732 michael 1372 * - name to which iline prefix will be prefixed to
733     * output - pointer to static string with prefixes listed in ascii form
734     * side effects - NONE
735     */
736     static const char *
737 michael 6506 show_iline_prefix(const struct Client *source_p, const struct MaskItem *conf)
738 michael 1372 {
739 michael 5985 static char prefix_of_host[USERLEN + 16];
740 michael 1372 char *prefix_ptr = prefix_of_host;
741    
742 michael 1715 if (IsConfWebIRC(conf))
743     *prefix_ptr++ = '<';
744 michael 1632 if (IsNoTilde(conf))
745 michael 1372 *prefix_ptr++ = '-';
746 michael 1632 if (IsNeedIdentd(conf))
747 michael 1372 *prefix_ptr++ = '+';
748 michael 1632 if (!IsNeedPassword(conf))
749 michael 1372 *prefix_ptr++ = '&';
750 michael 1632 if (IsConfExemptResv(conf))
751 michael 1372 *prefix_ptr++ = '$';
752 michael 1632 if (IsConfDoSpoofIp(conf))
753 michael 1372 *prefix_ptr++ = '=';
754 michael 6506 if (HasUMode(source_p, UMODE_OPER))
755     {
756     if (IsConfExemptKline(conf))
757     *prefix_ptr++ = '^';
758     if (IsConfExemptXline(conf))
759     *prefix_ptr++ = '!';
760     if (IsConfExemptLimits(conf))
761     *prefix_ptr++ = '>';
762     }
763    
764 michael 1632 if (IsConfCanFlood(conf))
765 michael 1372 *prefix_ptr++ = '|';
766    
767 michael 1632 strlcpy(prefix_ptr, conf->user, USERLEN+1);
768 michael 1372
769     return prefix_of_host;
770     }
771    
772 adx 30 static void
773 michael 3156 report_auth(struct Client *source_p, int parc, char *parv[])
774 michael 1372 {
775 michael 4032 const struct MaskItem *conf = NULL;
776 michael 4815 const dlink_node *node = NULL;
777 michael 1372
778 michael 3246 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
779 michael 1372 {
780 michael 4815 DLINK_FOREACH(node, atable[i].head)
781 michael 1372 {
782 michael 4815 const struct AddressRec *arec = node->data;
783 michael 1372
784 michael 1632 if (arec->type != CONF_CLIENT)
785     continue;
786 michael 1372
787 michael 1632 conf = arec->conf;
788 michael 1372
789 michael 6506 if (!HasUMode(source_p, UMODE_OPER) && IsConfDoSpoofIp(conf))
790 michael 1632 continue;
791 michael 1372
792 michael 4967 sendto_one_numeric(source_p, &me, RPL_STATSILINE, 'I',
793     conf->name == NULL ? "*" : conf->name,
794     show_iline_prefix(source_p, conf),
795     conf->host, conf->port,
796     conf->class->name);
797 michael 1372 }
798     }
799     }
800    
801     static void
802 michael 1457 stats_auth(struct Client *source_p, int parc, char *parv[])
803 adx 30 {
804     /* Oper only, if unopered, return ERR_NOPRIVILEGES */
805 michael 4340 if (ConfigGeneral.stats_i_oper_only == 2 && !HasUMode(source_p, UMODE_OPER))
806 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
807 adx 30
808 michael 4034 /* If unopered, only return matching auth blocks */
809 michael 4340 else if (ConfigGeneral.stats_i_oper_only == 1 && !HasUMode(source_p, UMODE_OPER))
810 adx 30 {
811 michael 4034 const struct MaskItem *conf = NULL;
812 adx 30
813     if (MyConnect(source_p))
814 michael 1632 conf = find_conf_by_address(source_p->host,
815 michael 4588 &source_p->connection->ip, CONF_CLIENT,
816     source_p->connection->aftype,
817 michael 2820 source_p->username,
818 michael 4588 source_p->connection->password, 1);
819 adx 30 else
820 michael 4034 conf = find_conf_by_address(source_p->host, NULL, CONF_CLIENT, 0,
821     source_p->username, NULL, 1);
822 adx 30
823 michael 1632 if (conf == NULL)
824 adx 30 return;
825    
826 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSILINE,
827     'I', "*", show_iline_prefix(source_p, conf),
828     conf->host, conf->port,
829 michael 4037 conf->class->name);
830 adx 30 }
831 michael 4034 else /* They are opered, or allowed to see all auth blocks */
832 michael 1457 report_auth(source_p, 0, NULL);
833 adx 30 }
834    
835 michael 1372 /* report_Klines()
836     * Inputs: Client to report to,
837     * type(==0 for perm, !=0 for temporary)
838 michael 2820 * mask
839 michael 1372 * Output: None
840 michael 3156 * Side effects: Reports configured K(or k)-lines to source_p.
841 michael 1372 */
842 adx 30 static void
843 michael 3156 report_Klines(struct Client *source_p, int tkline)
844 michael 1372 {
845 michael 4032 const struct MaskItem *conf = NULL;
846 michael 4815 const dlink_node *node = NULL;
847 michael 1921 char c = '\0';
848 michael 1372
849     if (tkline)
850 michael 1921 c = 'k';
851 michael 1372 else
852 michael 1921 c = 'K';
853 michael 1372
854 michael 3246 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
855 michael 1372 {
856 michael 4815 DLINK_FOREACH(node, atable[i].head)
857 michael 1372 {
858 michael 4815 const struct AddressRec *arec = node->data;
859 michael 1372
860 michael 1632 if (arec->type != CONF_KLINE)
861     continue;
862 michael 1628
863 michael 1632 conf = arec->conf;
864 michael 1372
865 michael 1650 if ((!tkline && conf->until) ||
866     (tkline && !conf->until))
867 michael 1632 continue;
868    
869 michael 4570 sendto_one_numeric(source_p, &me, RPL_STATSKLINE, c, conf->host, conf->user,
870     conf->reason);
871 michael 1372 }
872     }
873     }
874    
875     static void
876 michael 1457 stats_tklines(struct Client *source_p, int parc, char *parv[])
877 adx 30 {
878     /* Oper only, if unopered, return ERR_NOPRIVILEGES */
879 michael 4340 if (ConfigGeneral.stats_k_oper_only == 2 && !HasUMode(source_p, UMODE_OPER))
880 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
881 adx 30
882 michael 4034 /* If unopered, only return matching klines */
883 michael 4340 else if (ConfigGeneral.stats_k_oper_only == 1 && !HasUMode(source_p, UMODE_OPER))
884 adx 30 {
885 michael 4032 const struct MaskItem *conf = NULL;
886 adx 30
887     if (MyConnect(source_p))
888 michael 1632 conf = find_conf_by_address(source_p->host,
889 michael 4588 &source_p->connection->ip, CONF_KLINE,
890     source_p->connection->aftype,
891 michael 2820 source_p->username, NULL, 1);
892 adx 30 else
893 michael 4034 conf = find_conf_by_address(source_p->host, NULL, CONF_KLINE, 0,
894     source_p->username, NULL, 1);
895 adx 30
896 michael 1632 if (!conf)
897 adx 30 return;
898    
899 michael 5542 /* Don't report a permanent kline as temporary kline */
900 michael 1649 if (!conf->until)
901 adx 30 return;
902    
903 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSKLINE, 'k',
904     conf->host, conf->user, conf->reason);
905 adx 30 }
906 michael 4034 else /* They are opered, or allowed to see all klines */
907 adx 30 report_Klines(source_p, 1);
908     }
909    
910     static void
911 michael 1457 stats_klines(struct Client *source_p, int parc, char *parv[])
912 adx 30 {
913     /* Oper only, if unopered, return ERR_NOPRIVILEGES */
914 michael 4340 if (ConfigGeneral.stats_k_oper_only == 2 && !HasUMode(source_p, UMODE_OPER))
915 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
916 adx 30
917 michael 4034 /* If unopered, only return matching klines */
918 michael 4340 else if (ConfigGeneral.stats_k_oper_only == 1 && !HasUMode(source_p, UMODE_OPER))
919 adx 30 {
920 michael 4032 const struct MaskItem *conf = NULL;
921 adx 30
922 michael 4034 /* Search for a kline */
923 michael 560 if (MyConnect(source_p))
924 michael 1632 conf = find_conf_by_address(source_p->host,
925 michael 4588 &source_p->connection->ip, CONF_KLINE,
926     source_p->connection->aftype,
927 michael 2820 source_p->username, NULL, 0);
928 adx 30 else
929 michael 4034 conf = find_conf_by_address(source_p->host, NULL, CONF_KLINE, 0,
930     source_p->username, NULL, 0);
931 adx 30
932 michael 1632 if (!conf)
933 adx 30 return;
934    
935 michael 5542 /* Don't report a temporary kline as permanent kline */
936 michael 1649 if (conf->until)
937 adx 30 return;
938 michael 2820
939 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSKLINE, 'K',
940     conf->host, conf->user, conf->reason);
941 adx 30 }
942 michael 4034 else /* They are opered, or allowed to see all klines */
943 adx 30 report_Klines(source_p, 0);
944     }
945    
946     static void
947 michael 1457 stats_messages(struct Client *source_p, int parc, char *parv[])
948 adx 30 {
949 michael 5026 if (!HasUMode(source_p, UMODE_OPER) && ConfigGeneral.stats_m_oper_only)
950     sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
951     else
952     report_messages(source_p);
953 adx 30 }
954    
955     static void
956 michael 1457 stats_oper(struct Client *source_p, int parc, char *parv[])
957 adx 30 {
958 michael 4340 if (!HasUMode(source_p, UMODE_OPER) && ConfigGeneral.stats_o_oper_only)
959 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
960 adx 30 else
961 michael 1632 report_confitem_types(source_p, CONF_OPER);
962 adx 30 }
963    
964     /* stats_operedup()
965     *
966     * input - client pointer
967     * output - none
968     * side effects - client is shown a list of active opers
969     */
970     static void
971 michael 1457 stats_operedup(struct Client *source_p, int parc, char *parv[])
972 adx 30 {
973 michael 4815 const dlink_node *node = NULL;
974 michael 3511 unsigned int opercount = 0;
975 michael 3516 char buf[IRCD_BUFSIZE] = "";
976 adx 30
977 michael 4815 DLINK_FOREACH(node, oper_list.head)
978 adx 30 {
979 michael 4815 const struct Client *target_p = node->data;
980 adx 30
981 michael 1294 if (HasUMode(target_p, UMODE_HIDDEN) && !HasUMode(source_p, UMODE_OPER))
982 adx 30 continue;
983    
984 michael 3516 if (HasUMode(source_p, UMODE_OPER) || !HasUMode(target_p, UMODE_HIDEIDLE))
985 michael 6846 snprintf(buf, sizeof(buf), "%s", time_dissect(client_get_idle_time(source_p, target_p)));
986 michael 3516 else
987     strlcpy(buf, "n/a", sizeof(buf));
988    
989 michael 7051 if (MyConnect(source_p) && HasUMode(source_p, UMODE_OPER))
990 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
991 michael 3573 "p :[%c][%s] %s (%s@%s) Idle: %s",
992     HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O',
993 michael 4588 oper_privs_as_string(target_p->connection->operflags),
994 michael 3573 target_p->name, target_p->username, target_p->host, buf);
995 adx 30 else
996 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
997 michael 3573 "p :[%c] %s (%s@%s) Idle: %s",
998     HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O',
999     target_p->name, target_p->username, target_p->host, buf);
1000 michael 3511 ++opercount;
1001 adx 30 }
1002    
1003 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1004 michael 3573 "p :%u OPER(s)", opercount);
1005 adx 30 }
1006    
1007 michael 6366 /* show_ports()
1008     *
1009     * inputs - pointer to client to show ports to
1010     * output - none
1011     * side effects - send port listing to a client
1012     */
1013 adx 30 static void
1014 michael 6366 show_ports(struct Client *source_p)
1015     {
1016     char buf[IRCD_BUFSIZE] = "";
1017     char *p = NULL;
1018     const dlink_node *node = NULL;
1019    
1020     DLINK_FOREACH(node, listener_get_list()->head)
1021     {
1022     const struct Listener *listener = node->data;
1023     p = buf;
1024    
1025     if (listener->flags & LISTENER_HIDDEN)
1026     {
1027     if (!HasUMode(source_p, UMODE_ADMIN))
1028     continue;
1029     *p++ = 'H';
1030     }
1031    
1032     if (listener->flags & LISTENER_SERVER)
1033     *p++ = 'S';
1034     if (listener->flags & LISTENER_SSL)
1035     *p++ = 's';
1036     *p = '\0';
1037    
1038    
1039     if (HasUMode(source_p, UMODE_ADMIN) &&
1040 michael 7051 (MyConnect(source_p) || !ConfigServerHide.hide_server_ips))
1041 michael 6366 sendto_one_numeric(source_p, &me, RPL_STATSPLINE, 'P', listener->port,
1042     listener->name,
1043     listener->ref_count, buf,
1044     listener->active ? "active" : "disabled");
1045     else
1046     sendto_one_numeric(source_p, &me, RPL_STATSPLINE, 'P', listener->port,
1047     me.name, listener->ref_count, buf,
1048     listener->active ? "active" : "disabled");
1049     }
1050     }
1051    
1052     static void
1053 michael 1457 stats_ports(struct Client *source_p, int parc, char *parv[])
1054 adx 30 {
1055 michael 4340 if (!HasUMode(source_p, UMODE_OPER) && ConfigGeneral.stats_P_oper_only)
1056 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
1057 adx 30 else
1058     show_ports(source_p);
1059     }
1060    
1061     static void
1062 michael 1457 stats_resv(struct Client *source_p, int parc, char *parv[])
1063 adx 30 {
1064     report_resv(source_p);
1065     }
1066    
1067     static void
1068 michael 1457 stats_service(struct Client *source_p, int parc, char *parv[])
1069 adx 30 {
1070 michael 7248 report_service(source_p);
1071 michael 1175 }
1072    
1073     static void
1074 michael 1457 stats_tstats(struct Client *source_p, int parc, char *parv[])
1075 adx 30 {
1076 michael 4815 const dlink_node *node = NULL;
1077 michael 896 struct ServerStatistics tmp;
1078 michael 1842 struct ServerStatistics *sp = &tmp;
1079 michael 896
1080     memcpy(sp, &ServerStats, sizeof(struct ServerStatistics));
1081    
1082     /*
1083     * must use the += operator. is_sv is not the number of currently
1084     * active server connections. Note the incrementation in
1085     * s_bsd.c:close_connection.
1086     */
1087 michael 4213 sp->is_sv += dlink_list_length(&local_server_list);
1088 michael 896
1089 michael 4815 DLINK_FOREACH(node, local_server_list.head)
1090 michael 896 {
1091 michael 4815 const struct Client *target_p = node->data;
1092 michael 896
1093 michael 4588 sp->is_sbs += target_p->connection->send.bytes;
1094     sp->is_sbr += target_p->connection->recv.bytes;
1095     sp->is_sti += CurrentTime - target_p->connection->firsttime;
1096 michael 896 }
1097    
1098     sp->is_cl += dlink_list_length(&local_client_list);
1099    
1100 michael 4815 DLINK_FOREACH(node, local_client_list.head)
1101 michael 896 {
1102 michael 4815 const struct Client *target_p = node->data;
1103 michael 896
1104 michael 4588 sp->is_cbs += target_p->connection->send.bytes;
1105     sp->is_cbr += target_p->connection->recv.bytes;
1106     sp->is_cti += CurrentTime - target_p->connection->firsttime;
1107 michael 896 }
1108    
1109     sp->is_ni += dlink_list_length(&unknown_list);
1110    
1111 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1112 michael 4040 "t :accepts %u refused %u",
1113 michael 3573 sp->is_ac, sp->is_ref);
1114 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1115 michael 4040 "t :unknown commands %u prefixes %u",
1116 michael 3573 sp->is_unco, sp->is_unpf);
1117 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1118 michael 4040 "t :nick collisions %u unknown closes %u",
1119 michael 3573 sp->is_kill, sp->is_ni);
1120 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1121 michael 4040 "t :wrong direction %u empty %u",
1122 michael 3573 sp->is_wrdi, sp->is_empt);
1123 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1124 michael 4040 "t :numerics seen %u",
1125 michael 3573 sp->is_num);
1126 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1127 michael 4040 "t :auth successes %u fails %u",
1128 michael 3573 sp->is_asuc, sp->is_abad);
1129 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1130 michael 4040 "t :Client Server");
1131 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1132 michael 4040 "t :connected %u %u",
1133 michael 7330 sp->is_cl, sp->is_sv);
1134 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1135 michael 6782 "t :bytes sent %ju %ju",
1136 michael 3573 sp->is_cbs, sp->is_sbs);
1137 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1138 michael 6782 "t :bytes recv %ju %ju",
1139 michael 3573 sp->is_cbr, sp->is_sbr);
1140 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1141 michael 7330 "t :time connected %ju %ju",
1142     sp->is_cti, sp->is_sti);
1143 adx 30 }
1144    
1145     static void
1146 michael 1457 stats_uptime(struct Client *source_p, int parc, char *parv[])
1147 adx 30 {
1148 michael 4340 if (!HasUMode(source_p, UMODE_OPER) && ConfigGeneral.stats_u_oper_only)
1149 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
1150 michael 2269 else
1151     {
1152 michael 6569 sendto_one_numeric(source_p, &me, RPL_STATSUPTIME,
1153     time_dissect(CurrentTime - me.connection->since));
1154 michael 2269 if (!ConfigServerHide.disable_remote_commands || HasUMode(source_p, UMODE_OPER))
1155 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSCONN, Count.max_loc_con,
1156     Count.max_loc_cli, Count.totalrestartcount);
1157 michael 2269 }
1158 adx 30 }
1159    
1160     static void
1161 michael 1457 stats_shared(struct Client *source_p, int parc, char *parv[])
1162 adx 30 {
1163 michael 7209 report_shared(source_p);
1164     report_cluster(source_p);
1165 adx 30 }
1166    
1167     /* stats_servers()
1168     *
1169     * input - client pointer
1170     * output - none
1171     * side effects - client is shown lists of who connected servers
1172     */
1173     static void
1174 michael 1457 stats_servers(struct Client *source_p, int parc, char *parv[])
1175 adx 30 {
1176 michael 4815 const dlink_node *node = NULL;
1177 adx 30
1178 michael 4815 DLINK_FOREACH(node, local_server_list.head)
1179 adx 30 {
1180 michael 4815 const struct Client *target_p = node->data;
1181 adx 30
1182 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1183 michael 6846 "v :%s (%s!%s@%s) Idle: %s",
1184 michael 3573 target_p->name,
1185     (target_p->serv->by[0] ? target_p->serv->by : "Remote."),
1186 michael 6846 "*", "*", time_dissect(CurrentTime - target_p->connection->lasttime));
1187 adx 30 }
1188    
1189 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1190 michael 4213 "v :%u Server(s)",
1191     dlink_list_length(&local_server_list));
1192 adx 30 }
1193    
1194     static void
1195 michael 1457 stats_gecos(struct Client *source_p, int parc, char *parv[])
1196 adx 30 {
1197 michael 7304 report_gecos(source_p);
1198 adx 30 }
1199    
1200     static void
1201 michael 1457 stats_class(struct Client *source_p, int parc, char *parv[])
1202 adx 30 {
1203 michael 4815 const dlink_node *node = NULL;
1204 michael 2116
1205 michael 4815 DLINK_FOREACH(node, class_get_list()->head)
1206 michael 2116 {
1207 michael 4815 const struct ClassItem *class = node->data;
1208 michael 2116
1209 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSYLINE, 'Y',
1210     class->name, class->ping_freq,
1211     class->con_freq,
1212     class->max_total, class->max_sendq,
1213     class->max_recvq,
1214     class->ref_count,
1215     class->number_per_cidr, class->cidr_bitlen_ipv4,
1216     class->number_per_cidr, class->cidr_bitlen_ipv6,
1217     class->active ? "active" : "disabled");
1218 michael 2116 }
1219 adx 30 }
1220    
1221     static void
1222 michael 1457 stats_servlinks(struct Client *source_p, int parc, char *parv[])
1223 adx 30 {
1224 michael 6782 uintmax_t sendB = 0, recvB = 0;
1225 michael 7330 uintmax_t uptime = 0;
1226 michael 4815 dlink_node *node = NULL;
1227 adx 30
1228 michael 1219 if (ConfigServerHide.flatten_links && !HasUMode(source_p, UMODE_OPER))
1229 adx 30 {
1230 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
1231 adx 30 return;
1232     }
1233    
1234 michael 4815 DLINK_FOREACH(node, local_server_list.head)
1235 adx 30 {
1236 michael 4815 struct Client *target_p = node->data;
1237 adx 30
1238 michael 1851 if (HasFlag(target_p, FLAGS_SERVICE) && ConfigServerHide.hide_services)
1239     if (!HasUMode(source_p, UMODE_OPER))
1240     continue;
1241    
1242 michael 4588 sendB += target_p->connection->send.bytes;
1243     recvB += target_p->connection->recv.bytes;
1244 adx 30
1245 michael 6782 /* ":%s 211 %s %s %u %u %ju %u %ju :%u %u %s" */
1246 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSLINKINFO,
1247 michael 1219 get_client_name(target_p, HasUMode(source_p, UMODE_ADMIN) ? SHOW_IP : MASK_IP),
1248 michael 4588 dbuf_length(&target_p->connection->buf_sendq),
1249     target_p->connection->send.messages,
1250     target_p->connection->send.bytes >> 10,
1251     target_p->connection->recv.messages,
1252     target_p->connection->recv.bytes >> 10,
1253 michael 5531 (unsigned int)(CurrentTime - target_p->connection->firsttime),
1254     (CurrentTime > target_p->connection->since) ? (unsigned int)(CurrentTime - target_p->connection->since) : 0,
1255 michael 1219 HasUMode(source_p, UMODE_OPER) ? show_capabilities(target_p) : "TS");
1256 adx 30 }
1257    
1258     sendB >>= 10;
1259     recvB >>= 10;
1260    
1261 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT, "? :%u total server(s)",
1262 michael 4213 dlink_list_length(&local_server_list));
1263 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT, "? :Sent total: %7.2f %s",
1264 michael 3573 _GMKv(sendB), _GMKs(sendB));
1265 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT, "? :Recv total: %7.2f %s",
1266 michael 3573 _GMKv(recvB), _GMKs(recvB));
1267 adx 30
1268 michael 4588 uptime = (CurrentTime - me.connection->since);
1269 adx 30
1270 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1271 michael 3573 "? :Server send: %7.2f %s (%4.1f K/s)",
1272 michael 4588 _GMKv((me.connection->send.bytes>>10)),
1273     _GMKs((me.connection->send.bytes>>10)),
1274     (float)((float)((me.connection->send.bytes) >> 10) /
1275 michael 3573 (float)uptime));
1276 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1277 michael 3573 "? :Server recv: %7.2f %s (%4.1f K/s)",
1278 michael 4588 _GMKv((me.connection->recv.bytes>>10)),
1279     _GMKs((me.connection->recv.bytes>>10)),
1280     (float)((float)((me.connection->recv.bytes) >> 10) /
1281 michael 3573 (float)uptime));
1282 adx 30 }
1283    
1284 michael 1457 /* parse_stats_args()
1285     *
1286     * inputs - arg count
1287     * - args
1288     * - doall flag
1289     * - wild card or not
1290     * output - pointer to name to use
1291     * side effects -
1292     * common parse routine for m_stats args
1293 michael 2820 *
1294 michael 1457 */
1295 michael 4755 static const char *
1296 michael 3114 parse_stats_args(struct Client *source_p, int parc, char *parv[], int *doall, int *wilds)
1297 adx 30 {
1298 michael 1457 if (parc > 2)
1299 adx 30 {
1300 michael 4755 const char *name = parv[2];
1301 adx 30
1302 michael 3114 if (!irccmp(name, ID_or_name(&me, source_p)))
1303 michael 1457 *doall = 2;
1304 michael 3114 else if (!match(name, ID_or_name(&me, source_p)))
1305 michael 1457 *doall = 1;
1306    
1307     *wilds = has_wildcards(name);
1308    
1309     return name;
1310 adx 30 }
1311    
1312 michael 1457 return NULL;
1313 adx 30 }
1314    
1315     static void
1316 michael 4755 stats_L_list(struct Client *source_p, const char *name, int doall, int wilds,
1317     dlink_list *list, const char statchar)
1318 adx 30 {
1319 michael 4815 dlink_node *node = NULL;
1320 adx 30
1321     /*
1322 michael 4034 * Send info about connections which match, or all if the
1323     * mask matches from. Only restrictions are on those who
1324 adx 30 * are invisible not being visible to 'foreigners' who use
1325     * a wild card based search to list it.
1326     */
1327 michael 4815 DLINK_FOREACH(node, list->head)
1328 adx 30 {
1329 michael 4815 struct Client *target_p = node->data;
1330 adx 30
1331 michael 1219 if (HasUMode(target_p, UMODE_INVISIBLE) && (doall || wilds) &&
1332 michael 1457 !(MyConnect(source_p) && HasUMode(source_p, UMODE_OPER)) &&
1333     !HasUMode(target_p, UMODE_OPER) && (target_p != source_p))
1334 adx 30 continue;
1335 michael 4034
1336 michael 1652 if (!doall && wilds && match(name, target_p->name))
1337 adx 30 continue;
1338 michael 4034
1339 adx 30 if (!(doall || wilds) && irccmp(name, target_p->name))
1340     continue;
1341    
1342 michael 4034 /*
1343     * This basically shows ips for our opers if it's not a server/admin, or
1344 michael 4298 * it's one of our admins.
1345 michael 4034 */
1346 michael 7051 if (MyConnect(source_p) && HasUMode(source_p, UMODE_OPER) &&
1347 michael 3655 (HasUMode(source_p, UMODE_ADMIN) ||
1348     (!IsServer(target_p) && !HasUMode(target_p, UMODE_ADMIN) &&
1349     !IsHandshake(target_p) && !IsConnecting(target_p))))
1350 adx 30 {
1351 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSLINKINFO,
1352 adx 30 (IsUpper(statchar)) ?
1353     get_client_name(target_p, SHOW_IP) :
1354     get_client_name(target_p, HIDE_IP),
1355 michael 4588 dbuf_length(&target_p->connection->buf_sendq),
1356     target_p->connection->send.messages,
1357     target_p->connection->send.bytes>>10,
1358     target_p->connection->recv.messages,
1359     target_p->connection->recv.bytes>>10,
1360 michael 5531 (unsigned int)(CurrentTime - target_p->connection->firsttime),
1361     (CurrentTime > target_p->connection->since) ? (unsigned int)(CurrentTime - target_p->connection->since) : 0,
1362 adx 30 IsServer(target_p) ? show_capabilities(target_p) : "-");
1363     }
1364     else
1365     {
1366 michael 4967 /* If it's a server, mask the real IP */
1367     if (IsServer(target_p) || IsHandshake(target_p) || IsConnecting(target_p))
1368 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSLINKINFO,
1369 michael 1457 get_client_name(target_p, MASK_IP),
1370 michael 4588 dbuf_length(&target_p->connection->buf_sendq),
1371     target_p->connection->send.messages,
1372     target_p->connection->send.bytes>>10,
1373     target_p->connection->recv.messages,
1374     target_p->connection->recv.bytes>>10,
1375 michael 5531 (unsigned int)(CurrentTime - target_p->connection->firsttime),
1376     (CurrentTime > target_p->connection->since) ? (unsigned int)(CurrentTime - target_p->connection->since):0,
1377 michael 1457 IsServer(target_p) ? show_capabilities(target_p) : "-");
1378 adx 30 else /* show the real IP */
1379 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSLINKINFO,
1380 michael 1457 (IsUpper(statchar)) ?
1381     get_client_name(target_p, SHOW_IP) :
1382     get_client_name(target_p, HIDE_IP),
1383 michael 4588 dbuf_length(&target_p->connection->buf_sendq),
1384     target_p->connection->send.messages,
1385     target_p->connection->send.bytes>>10,
1386     target_p->connection->recv.messages,
1387     target_p->connection->recv.bytes>>10,
1388 michael 5531 (unsigned int)(CurrentTime - target_p->connection->firsttime),
1389     (CurrentTime > target_p->connection->since) ? (unsigned int)(CurrentTime - target_p->connection->since):0,
1390 michael 1457 IsServer(target_p) ? show_capabilities(target_p) : "-");
1391 adx 30 }
1392     }
1393     }
1394    
1395 michael 1457 /*
1396     * stats_L
1397 adx 30 *
1398 michael 1457 * inputs - pointer to client to report to
1399     * - doall flag
1400     * - wild card or not
1401     * output - NONE
1402     * side effects -
1403     */
1404     static void
1405 michael 4755 stats_L(struct Client *source_p, const char *name, int doall,
1406     int wilds, const char statchar)
1407 michael 1457 {
1408     stats_L_list(source_p, name, doall, wilds, &unknown_list, statchar);
1409     stats_L_list(source_p, name, doall, wilds, &local_client_list, statchar);
1410 michael 4213 stats_L_list(source_p, name, doall, wilds, &local_server_list, statchar);
1411 michael 1457 }
1412    
1413     static void
1414     stats_ltrace(struct Client *source_p, int parc, char *parv[])
1415     {
1416     int doall = 0;
1417     int wilds = 0;
1418 michael 4755 const char *name = NULL;
1419 michael 1457
1420 michael 3246 if ((name = parse_stats_args(source_p, parc, parv, &doall, &wilds)))
1421 michael 1457 {
1422 michael 4755 const char statchar = *parv[1];
1423 michael 1457 stats_L(source_p, name, doall, wilds, statchar);
1424     }
1425     else
1426 michael 3109 sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "STATS");
1427 michael 1457 }
1428    
1429 michael 6552 struct StatsStruct
1430 michael 1457 {
1431     const unsigned char letter;
1432 michael 4479 void (*handler)(struct Client *, int, char *[]);
1433 michael 6552 const unsigned int required_modes;
1434 michael 1457 };
1435    
1436 michael 6552 static const struct StatsStruct *stats_map[256];
1437     static const struct StatsStruct stats_tab[] =
1438     {
1439     { 'a', stats_dns_servers, UMODE_ADMIN },
1440     { 'A', stats_dns_servers, UMODE_ADMIN },
1441     { 'c', stats_connect, UMODE_OPER },
1442     { 'C', stats_connect, UMODE_OPER },
1443     { 'd', stats_tdeny, UMODE_OPER },
1444     { 'D', stats_deny, UMODE_OPER },
1445     { 'e', stats_exempt, UMODE_OPER },
1446     { 'E', stats_events, UMODE_ADMIN },
1447     { 'f', fd_dump, UMODE_ADMIN },
1448     { 'F', fd_dump, UMODE_ADMIN },
1449     { 'h', stats_hubleaf, UMODE_OPER },
1450     { 'H', stats_hubleaf, UMODE_OPER },
1451     { 'i', stats_auth, 0 },
1452     { 'I', stats_auth, 0 },
1453     { 'k', stats_tklines, 0 },
1454     { 'K', stats_klines, 0 },
1455     { 'l', stats_ltrace, UMODE_OPER },
1456     { 'L', stats_ltrace, UMODE_OPER },
1457     { 'm', stats_messages, 0 },
1458     { 'M', stats_messages, 0 },
1459     { 'o', stats_oper, 0 },
1460     { 'O', stats_oper, 0 },
1461     { 'p', stats_operedup, 0 },
1462     { 'P', stats_ports, 0 },
1463     { 'q', stats_resv, UMODE_OPER },
1464     { 'Q', stats_resv, UMODE_OPER },
1465     { 'r', stats_usage, UMODE_OPER },
1466     { 'R', stats_usage, UMODE_OPER },
1467     { 's', stats_service, UMODE_OPER },
1468     { 'S', stats_service, UMODE_OPER },
1469     { 't', stats_tstats, UMODE_OPER },
1470     { 'T', motd_report, UMODE_OPER },
1471     { 'u', stats_uptime, 0 },
1472     { 'U', stats_shared, UMODE_OPER },
1473     { 'v', stats_servers, UMODE_OPER },
1474     { 'x', stats_gecos, UMODE_OPER },
1475     { 'X', stats_gecos, UMODE_OPER },
1476     { 'y', stats_class, UMODE_OPER },
1477     { 'Y', stats_class, UMODE_OPER },
1478     { 'z', stats_memory, UMODE_OPER },
1479     { '?', stats_servlinks, 0 },
1480     { '\0', NULL, 0 }
1481     };
1482    
1483 michael 1457 static void
1484     do_stats(struct Client *source_p, int parc, char *parv[])
1485     {
1486 michael 6552 const unsigned char statchar = *parv[1];
1487     const struct StatsStruct *tab;
1488 michael 1457
1489     if (statchar == '\0')
1490     {
1491 michael 3109 sendto_one_numeric(source_p, &me, RPL_ENDOFSTATS, '*');
1492 michael 1457 return;
1493     }
1494    
1495 michael 6552 if ((tab = stats_map[statchar]))
1496 michael 1457 {
1497 michael 6552 if (!tab->required_modes || HasUMode(source_p, tab->required_modes))
1498     tab->handler(source_p, parc, parv);
1499     else
1500     sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
1501 michael 1457
1502 michael 6552 sendto_realops_flags(UMODE_SPY, L_ALL, SEND_NOTICE,
1503     "STATS %c requested by %s (%s@%s) [%s]",
1504     statchar, source_p->name, source_p->username,
1505     source_p->host, source_p->servptr->name);
1506 michael 1457 }
1507    
1508 michael 3109 sendto_one_numeric(source_p, &me, RPL_ENDOFSTATS, statchar);
1509 michael 1457 }
1510    
1511     /*
1512     * m_stats()
1513 michael 3096 * parv[0] = command
1514 michael 1457 * parv[1] = stat letter/command
1515     * parv[2] = (if present) server/mask in stats L
1516 adx 30 */
1517 michael 2820 static int
1518 michael 3156 m_stats(struct Client *source_p, int parc, char *parv[])
1519 adx 30 {
1520 michael 7330 static uintmax_t last_used = 0;
1521 adx 30
1522 michael 4298 /* Check the user is actually allowed to do /stats, and isn't flooding */
1523 michael 4340 if ((last_used + ConfigGeneral.pace_wait) > CurrentTime)
1524 michael 1457 {
1525 michael 4759 sendto_one_numeric(source_p, &me, RPL_LOAD2HI, "STATS");
1526 michael 2820 return 0;
1527 michael 1457 }
1528 adx 30
1529 michael 1457 last_used = CurrentTime;
1530 adx 30
1531 michael 2341 /* Is the stats meant for us? */
1532     if (!ConfigServerHide.disable_remote_commands)
1533 michael 4034 if (hunt_server(source_p, ":%s STATS %s :%s", 2, parc, parv) != HUNTED_ISME)
1534 michael 2820 return 0;
1535 michael 2341
1536 michael 1457 do_stats(source_p, parc, parv);
1537 michael 2820 return 0;
1538 michael 1457 }
1539    
1540     /*
1541 michael 3219 * ms_stats()
1542 michael 3096 * parv[0] = command
1543 michael 1457 * parv[1] = stat letter/command
1544     * parv[2] = (if present) server/mask in stats L, or target
1545     */
1546 michael 2820 static int
1547 michael 3219 ms_stats(struct Client *source_p, int parc, char *parv[])
1548 michael 1457 {
1549 michael 4034 if (hunt_server(source_p, ":%s STATS %s :%s", 2, parc, parv) != HUNTED_ISME)
1550 michael 2820 return 0;
1551 michael 1457
1552     do_stats(source_p, parc, parv);
1553 michael 2820 return 0;
1554 adx 30 }
1555 michael 1230
1556 michael 6552 static void
1557     stats_init(void)
1558     {
1559     for (const struct StatsStruct *tab = stats_tab; tab->letter; ++tab)
1560     stats_map[tab->letter] = tab;
1561     }
1562    
1563 michael 2820 static struct Message stats_msgtab =
1564     {
1565 michael 5881 .cmd = "STATS",
1566     .args_min = 2,
1567     .args_max = MAXPARA,
1568     .handlers[UNREGISTERED_HANDLER] = m_unregistered,
1569     .handlers[CLIENT_HANDLER] = m_stats,
1570     .handlers[SERVER_HANDLER] = ms_stats,
1571     .handlers[ENCAP_HANDLER] = m_ignore,
1572     .handlers[OPER_HANDLER] = ms_stats
1573 michael 1230 };
1574    
1575     static void
1576     module_init(void)
1577     {
1578 michael 6552 stats_init();
1579 michael 1230 mod_add_cmd(&stats_msgtab);
1580     }
1581    
1582     static void
1583     module_exit(void)
1584     {
1585     mod_del_cmd(&stats_msgtab);
1586     }
1587    
1588 michael 2820 struct module module_entry =
1589     {
1590 michael 1230 .version = "$Revision$",
1591     .modinit = module_init,
1592     .modexit = module_exit,
1593     };

Properties

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