ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_stats.c
Revision: 7963
Committed: Mon Mar 13 18:50:04 2017 UTC (9 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 42716 byte(s)
Log Message:
- No longer put servers on the 'global_client_list'. This was just bad.

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 7924 * Copyright (c) 1997-2017 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 michael 2820 #include "event.h"
47 adx 30 #include "parse.h"
48     #include "modules.h"
49     #include "whowas.h"
50 michael 884 #include "watch.h"
51 michael 6836 #include "reslib.h"
52 michael 2150 #include "motd.h"
53 michael 4325 #include "ipcache.h"
54 adx 30
55    
56 michael 7209 static void
57     report_shared(struct Client *source_p)
58 michael 1922 {
59 michael 7218 static const struct shared_types
60 michael 7209 {
61     unsigned int type;
62     unsigned char letter;
63     } flag_table[] = {
64     { SHARED_KLINE, 'K' },
65     { SHARED_UNKLINE, 'U' },
66     { SHARED_XLINE, 'X' },
67     { SHARED_UNXLINE, 'Y' },
68     { SHARED_RESV, 'Q' },
69     { SHARED_UNRESV, 'R' },
70     { SHARED_LOCOPS, 'L' },
71     { SHARED_DLINE, 'D' },
72     { SHARED_UNDLINE, 'E' },
73     { 0, '\0' }
74     };
75 michael 1922
76 michael 7209 dlink_node *node;
77 michael 7425 char buf[sizeof(flag_table) / sizeof(struct shared_types) + 1]; /* +1 for 'c' */
78 michael 7209
79     DLINK_FOREACH(node, shared_get_list()->head)
80     {
81 michael 7218 const struct SharedItem *shared = node->data;
82 michael 7209 char *p = buf;
83    
84     *p++ = 'c';
85    
86 michael 7218 for (const struct shared_types *tab = flag_table; tab->type; ++tab)
87     if (tab->type & shared->type)
88     *p++ = tab->letter;
89 michael 7209 else
90 michael 7218 *p++ = ToLower(tab->letter);
91 michael 7209
92     *p = '\0';
93    
94 michael 7218 sendto_one_numeric(source_p, &me, RPL_STATSULINE, shared->server,
95     shared->user, shared->host, buf);
96 michael 7209 }
97     }
98    
99     static void
100     report_cluster(struct Client *source_p)
101     {
102 michael 7218 static const struct cluster_types
103 michael 7209 {
104     unsigned int type;
105     unsigned char letter;
106     } flag_table[] = {
107     { CLUSTER_KLINE, 'K' },
108     { CLUSTER_UNKLINE, 'U' },
109     { CLUSTER_XLINE, 'X' },
110     { CLUSTER_UNXLINE, 'Y' },
111     { CLUSTER_RESV, 'Q' },
112     { CLUSTER_UNRESV, 'R' },
113     { CLUSTER_LOCOPS, 'L' },
114     { CLUSTER_DLINE, 'D' },
115     { CLUSTER_UNDLINE, 'E' },
116     { 0, '\0' }
117     };
118    
119     dlink_node *node;
120 michael 7425 char buf[sizeof(flag_table) / sizeof(struct cluster_types) + 1]; /* +1 for 'C' */
121 michael 7209
122     DLINK_FOREACH(node, cluster_get_list()->head)
123     {
124 michael 7218 const struct ClusterItem *cluster = node->data;
125 michael 7209 char *p = buf;
126    
127     *p++ = 'C';
128    
129 michael 7218 for (const struct cluster_types *tab = flag_table; tab->type; ++tab)
130     if (tab->type & cluster->type)
131     *p++ = tab->letter;
132 michael 7209 else
133 michael 7218 *p++ = ToLower(tab->letter);
134 michael 7209
135     *p = '\0';
136    
137 michael 7218 sendto_one_numeric(source_p, &me, RPL_STATSULINE, cluster->server,
138 michael 7209 "*", "*", buf);
139     }
140     }
141    
142 michael 7248 static void
143 michael 7397 stats_service(struct Client *source_p, int parc, char *parv[])
144 michael 7248 {
145     dlink_node *node;
146    
147     DLINK_FOREACH(node, service_get_list()->head)
148     {
149     const struct ServiceItem *service = node->data;
150     sendto_one_numeric(source_p, &me, RPL_STATSSERVICE, 'S', "*", service->name, 0, 0);
151     }
152     }
153    
154 michael 7304 static void
155 michael 7397 stats_gecos(struct Client *source_p, int parc, char *parv[])
156 michael 7304 {
157     dlink_node *node;
158    
159     DLINK_FOREACH(node, gecos_get_list()->head)
160     {
161     const struct GecosItem *gecos = node->data;
162     sendto_one_numeric(source_p, &me, RPL_STATSXLINE,
163 michael 7313 gecos->expire ? 'x' : 'X',
164 michael 7304 gecos->mask, gecos->reason);
165     }
166     }
167    
168 adx 30 /*
169 michael 1922 * inputs - pointer to client requesting confitem report
170     * - ConfType to report
171     * output - none
172     * side effects -
173     */
174     static void
175 michael 7405 stats_operator(struct Client *source_p, int parc, char *parv[])
176 michael 1922 {
177 michael 7405 dlink_node *node;
178 michael 1922
179 michael 7405 if (!HasUMode(source_p, UMODE_OPER) && ConfigGeneral.stats_o_oper_only)
180 michael 1922 {
181 michael 7405 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
182     return;
183     }
184 michael 1922
185 michael 7405 DLINK_FOREACH(node, operator_items.head)
186     {
187     const struct MaskItem *conf = node->data;
188 michael 1922
189 michael 7405 /* Don't allow non opers to see oper privs */
190     if (HasUMode(source_p, UMODE_OPER))
191     sendto_one_numeric(source_p, &me, RPL_STATSOLINE, 'O', conf->user, conf->host,
192     conf->name, oper_privs_as_string(conf->port),
193     conf->class->name);
194     else
195     sendto_one_numeric(source_p, &me, RPL_STATSOLINE, 'O', conf->user, conf->host,
196     conf->name, "0", conf->class->name);
197     }
198     }
199 michael 1922
200 michael 7405 static void
201     stats_connect(struct Client *source_p, int parc, char *parv[])
202     {
203     dlink_node *node;
204 michael 1922
205 michael 7405 DLINK_FOREACH(node, connect_items.head)
206     {
207     char buf[8];
208     char *p = buf;
209     const struct MaskItem *conf = node->data;
210 michael 1922
211 michael 7405 if (IsConfAllowAutoConn(conf))
212     *p++ = 'A';
213     if (IsConfSSL(conf))
214     *p++ = 'S';
215     if (p == buf)
216     *p++ = '*';
217 michael 4034
218 michael 7405 *p = '\0';
219 michael 4034
220 michael 7405 /*
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     else
228     sendto_one_numeric(source_p, &me, RPL_STATSCLINE, 'C',
229     "*@127.0.0.1", buf, conf->name, conf->port,
230     conf->class->name);
231 michael 1922 }
232     }
233    
234 michael 1927 /* report_resv()
235     *
236     * inputs - pointer to client pointer to report to.
237     * output - NONE
238     * side effects - report all resvs to client.
239     */
240     static void
241 michael 7397 stats_resv(struct Client *source_p, int parc, char *parv[])
242 michael 1927 {
243 michael 7687 dlink_node *node;
244 michael 1927
245 michael 7282 DLINK_FOREACH(node, resv_chan_get_list()->head)
246 michael 1927 {
247 michael 7282 const struct ResvItem *resv = node->data;
248 michael 3109
249     sendto_one_numeric(source_p, &me, RPL_STATSQLINE,
250 michael 7282 resv->expire ? 'q' : 'Q',
251     resv->mask, resv->reason);
252 michael 1927 }
253    
254 michael 7282 DLINK_FOREACH(node, resv_nick_get_list()->head)
255 michael 1927 {
256 michael 7282 const struct ResvItem *resv = node->data;
257 michael 3109
258     sendto_one_numeric(source_p, &me, RPL_STATSQLINE,
259 michael 7282 resv->expire ? 'q' : 'Q',
260     resv->mask, resv->reason);
261 michael 1927 }
262     }
263    
264 adx 30 static void
265 michael 1457 stats_memory(struct Client *source_p, int parc, char *parv[])
266 adx 30 {
267 michael 7687 dlink_node *node, *node2;
268 adx 30
269 michael 948 unsigned int local_client_conf_count = 0; /* local client conf links */
270 adx 30
271 michael 1017 unsigned int channel_members = 0;
272 michael 948 unsigned int channel_invites = 0;
273     unsigned int channel_bans = 0;
274     unsigned int channel_except = 0;
275     unsigned int channel_invex = 0;
276 adx 30
277 michael 948 unsigned int wwu = 0; /* whowas users */
278 michael 4329 unsigned int number_ips_stored = 0; /* number of ip addresses hashed */
279 adx 30
280 michael 6719 size_t channel_ban_memory = 0;
281     size_t channel_except_memory = 0;
282     size_t channel_invex_memory = 0;
283 adx 30
284     unsigned int safelist_count = 0;
285 michael 6719 size_t safelist_memory = 0;
286 adx 30
287 michael 6719 size_t wwm = 0; /* whowas array memory used */
288     size_t mem_ips_stored = 0; /* memory used by ip address hash */
289 adx 30
290     unsigned int local_client_count = 0;
291     unsigned int remote_client_count = 0;
292    
293 michael 6719 size_t local_client_memory_used = 0;
294     size_t remote_client_memory_used = 0;
295 adx 30
296 michael 1017 unsigned int watch_list_headers = 0; /* watchlist headers */
297     unsigned int watch_list_entries = 0; /* watchlist entries */
298 michael 6719 size_t watch_list_memory = 0; /* watchlist memory used */
299 michael 884
300 michael 7349 unsigned int listener_count = 0;
301     size_t listener_memory = 0;
302 adx 30
303 michael 7349
304 michael 7963 DLINK_FOREACH(node, global_server_list.head)
305     {
306     const struct Client *target_p = node->data;
307    
308     if (MyConnect(target_p))
309     {
310     ++local_client_count;
311     local_client_conf_count += dlink_list_length(&target_p->connection->confs);
312     }
313     else
314     ++remote_client_count;
315     }
316    
317 michael 7433 DLINK_FOREACH(node, global_client_list.head)
318 adx 30 {
319 michael 7433 const struct Client *target_p = node->data;
320 adx 30
321     if (MyConnect(target_p))
322     {
323     ++local_client_count;
324 michael 4588 local_client_conf_count += dlink_list_length(&target_p->connection->confs);
325     watch_list_entries += dlink_list_length(&target_p->connection->watches);
326 adx 30 }
327     else
328     ++remote_client_count;
329     }
330    
331 michael 7605 /* Count up all members, invites, ban lists, except lists, Invex lists */
332 michael 7433 DLINK_FOREACH(node, channel_list.head)
333 adx 30 {
334 michael 7433 const struct Channel *chptr = node->data;
335 adx 30
336 michael 1017 channel_members += dlink_list_length(&chptr->members);
337 adx 30 channel_invites += dlink_list_length(&chptr->invites);
338    
339 michael 1017 channel_bans += dlink_list_length(&chptr->banlist);
340     channel_ban_memory += dlink_list_length(&chptr->banlist) * sizeof(struct Ban);
341    
342     channel_except += dlink_list_length(&chptr->exceptlist);
343     channel_except_memory += dlink_list_length(&chptr->exceptlist) * sizeof(struct Ban);
344    
345     channel_invex += dlink_list_length(&chptr->invexlist);
346     channel_invex_memory += dlink_list_length(&chptr->invexlist) * sizeof(struct Ban);
347 adx 30 }
348    
349 michael 7471 safelist_count = dlink_list_length(&listing_client_list);
350     if (safelist_count)
351 adx 30 {
352     safelist_memory = safelist_count * sizeof(struct ListTask);
353 michael 7433
354     DLINK_FOREACH(node, listing_client_list.head)
355 adx 30 {
356 michael 7433 const struct Client *acptr = node->data;
357 adx 30
358 michael 7433 DLINK_FOREACH(node2, acptr->connection->list_task->show_mask.head)
359     safelist_memory += strlen(node2->data);
360 adx 30
361 michael 7433 DLINK_FOREACH(node2, acptr->connection->list_task->hide_mask.head)
362     safelist_memory += strlen(node2->data);
363 adx 30 }
364     }
365    
366 michael 1017 watch_count_memory(&watch_list_headers, &watch_list_memory);
367 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
368 michael 7616 "z :WATCH headers %u(%zu) entries %u(%zu)",
369 michael 3573 watch_list_headers,
370 michael 7616 watch_list_memory,
371     watch_list_entries,
372 michael 3573 watch_list_entries * sizeof(dlink_node) * 2);
373 michael 884
374 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
375 michael 7616 "z :Clients %u(%zu)",
376 michael 7963 dlink_list_length(&global_client_list),
377     dlink_list_length(&global_client_list) * sizeof(struct Client));
378 adx 30
379 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
380 michael 6719 "z :Attached confs %u(%zu)",
381 michael 3573 local_client_conf_count,
382 michael 6719 local_client_conf_count * sizeof(dlink_node));
383 adx 30
384 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
385 michael 6719 "z :Resv channels %u(%zu) nicks %u(%zu)",
386 michael 7282 dlink_list_length(resv_chan_get_list()),
387     dlink_list_length(resv_chan_get_list()) * sizeof(struct ResvItem),
388     dlink_list_length(resv_nick_get_list()),
389     dlink_list_length(resv_nick_get_list()) * sizeof(struct ResvItem));
390 adx 30
391 michael 7349 listener_count_memory(&listener_count, &listener_memory);
392 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
393 michael 7467 "z :Listeners %u(%zu)",
394 michael 7349 listener_count, listener_memory);
395    
396     sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
397 michael 6719 "z :Classes %u(%zu)",
398 michael 7471 dlink_list_length(class_get_list()),
399     dlink_list_length(class_get_list()) * sizeof(struct ClassItem));
400 adx 30
401 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
402 michael 7603 "z :Channels %u(%zu)",
403 michael 7605 dlink_list_length(&channel_list),
404     dlink_list_length(&channel_list) * sizeof(struct Channel));
405 adx 30
406 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
407 michael 6719 "z :Bans %u(%zu)",
408 michael 3573 channel_bans, channel_ban_memory);
409 adx 30
410 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
411 michael 6719 "z :Exceptions %u(%zu)",
412 michael 3573 channel_except, channel_except_memory);
413 adx 30
414 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
415 michael 6719 "z :Invex %u(%zu)",
416 michael 3573 channel_invex, channel_invex_memory);
417 adx 30
418 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
419 michael 6719 "z :Channel members %u(%zu) invites %u(%zu)",
420 michael 3573 channel_members,
421 michael 6719 channel_members * sizeof(struct Membership),
422     channel_invites,
423 michael 7607 channel_invites * sizeof(struct Invite));
424 adx 30
425 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
426 michael 6719 "z :Safelist %u(%zu)",
427 michael 3573 safelist_count, safelist_memory);
428 adx 30
429 michael 7437 whowas_count_memory(&wwu, &wwm);
430 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
431 michael 7437 "z :Whowas users %u(%zu)", wwu, wwm);
432 adx 30
433 michael 2150 motd_memory_count(source_p);
434 michael 7471
435 michael 4325 ipcache_get_stats(&number_ips_stored, &mem_ips_stored);
436 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
437 michael 6719 "z :iphash %u(%zu)",
438 michael 3573 number_ips_stored, mem_ips_stored);
439 adx 30
440 michael 7471 local_client_memory_used = local_client_count *(sizeof(struct Client) + sizeof(struct Connection));
441 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
442 michael 6719 "z :Local client Memory in use: %u(%zu)",
443 michael 3573 local_client_count, local_client_memory_used);
444 adx 30
445     remote_client_memory_used = remote_client_count * sizeof(struct Client);
446 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
447 michael 6719 "z :Remote client Memory in use: %u(%zu)",
448 michael 3573 remote_client_count, remote_client_memory_used);
449 adx 30 }
450    
451     static void
452 michael 4479 stats_dns_servers(struct Client *source_p, int parc, char *parv[])
453 adx 30 {
454 michael 6836 char ipaddr[HOSTIPLEN + 1] = "";
455    
456     for (unsigned int i = 0; i < irc_nscount; ++i)
457     {
458     getnameinfo((const struct sockaddr *)&(irc_nsaddr_list[i]),
459     irc_nsaddr_list[i].ss_len, ipaddr,
460     sizeof(ipaddr), NULL, 0, NI_NUMERICHOST);
461     sendto_one_numeric(source_p, &me, RPL_STATSALINE, ipaddr);
462 michael 6990 }
463 adx 30 }
464    
465     /* stats_deny()
466     *
467     * input - client to report to
468     * output - none
469     * side effects - client is given dline list.
470     */
471     static void
472 michael 1457 stats_deny(struct Client *source_p, int parc, char *parv[])
473 adx 30 {
474 michael 7687 dlink_node *node;
475 adx 30
476 michael 3246 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
477 adx 30 {
478 michael 4815 DLINK_FOREACH(node, atable[i].head)
479 adx 30 {
480 michael 4815 const struct AddressRec *arec = node->data;
481 michael 1367
482 michael 1632 if (arec->type != CONF_DLINE)
483     continue;
484 adx 30
485 michael 7471 const struct MaskItem *conf = arec->conf;
486 michael 5542 /* Don't report a temporary dline as permanent dline */
487 michael 1649 if (conf->until)
488 michael 1632 continue;
489 adx 30
490 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSDLINE, 'D', conf->host, conf->reason);
491 adx 30 }
492     }
493     }
494    
495     /* stats_tdeny()
496     *
497     * input - client to report to
498     * output - none
499     * side effects - client is given dline list.
500     */
501     static void
502 michael 1457 stats_tdeny(struct Client *source_p, int parc, char *parv[])
503 adx 30 {
504 michael 7687 dlink_node *node;
505 adx 30
506 michael 3246 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
507 adx 30 {
508 michael 4815 DLINK_FOREACH(node, atable[i].head)
509 adx 30 {
510 michael 4815 const struct AddressRec *arec = node->data;
511 michael 1367
512 michael 1632 if (arec->type != CONF_DLINE)
513     continue;
514 adx 30
515 michael 7471 const struct MaskItem *conf = arec->conf;
516 michael 5542 /* Don't report a permanent dline as temporary dline */
517 michael 1649 if (!conf->until)
518 michael 1632 continue;
519 adx 30
520 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSDLINE, 'd', conf->host, conf->reason);
521 adx 30 }
522     }
523     }
524    
525     /* stats_exempt()
526     *
527     * input - client to report to
528     * output - none
529     * side effects - client is given list of exempt blocks
530     */
531     static void
532 michael 1457 stats_exempt(struct Client *source_p, int parc, char *parv[])
533 adx 30 {
534 michael 7687 dlink_node *node;
535 adx 30
536 michael 4340 if (ConfigGeneral.stats_e_disabled)
537 michael 584 {
538 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
539 michael 584 return;
540     }
541    
542 michael 3246 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
543 adx 30 {
544 michael 4815 DLINK_FOREACH(node, atable[i].head)
545 adx 30 {
546 michael 4815 const struct AddressRec *arec = node->data;
547 michael 1367
548 michael 1632 if (arec->type != CONF_EXEMPT)
549     continue;
550 adx 30
551 michael 7471 const struct MaskItem *conf = arec->conf;
552 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSDLINE, 'e', conf->host, "");
553 adx 30 }
554     }
555     }
556    
557     static void
558 michael 1457 stats_events(struct Client *source_p, int parc, char *parv[])
559 adx 30 {
560 michael 7687 dlink_node *node;
561 michael 6306
562     sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
563     "E :Operation Next Execution");
564     sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
565     "E :---------------------------------------------");
566    
567     DLINK_FOREACH(node, event_get_list()->head)
568     {
569     const struct event *ev = node->data;
570    
571     sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
572 michael 7458 "E :%-30s %-4ji seconds",
573     ev->name, ev->next - CurrentTime);
574 michael 6306 }
575 adx 30 }
576    
577     static void
578 michael 1457 stats_hubleaf(struct Client *source_p, int parc, char *parv[])
579 adx 30 {
580 michael 7687 dlink_node *node, *node2;
581 michael 2118
582 michael 7401 DLINK_FOREACH(node, connect_items.head)
583 michael 2118 {
584 michael 4815 const struct MaskItem *conf = node->data;
585 michael 2118
586 michael 7460 DLINK_FOREACH(node2, conf->hub_list.head)
587     sendto_one_numeric(source_p, &me, RPL_STATSHLINE, 'H', node2->data, conf->name, 0, "*");
588 michael 2118 }
589    
590 michael 7401 DLINK_FOREACH(node, connect_items.head)
591 michael 2118 {
592 michael 4815 const struct MaskItem *conf = node->data;
593 michael 2118
594 michael 7460 DLINK_FOREACH(node2, conf->leaf_list.head)
595     sendto_one_numeric(source_p, &me, RPL_STATSLLINE, 'L', node2->data, conf->name, 0, "*");
596 michael 2118 }
597 adx 30 }
598    
599 michael 1372 /*
600     * show_iline_prefix()
601     *
602     * inputs - pointer to struct Client requesting output
603 michael 2820 * - pointer to struct MaskItem
604 michael 1372 * - name to which iline prefix will be prefixed to
605     * output - pointer to static string with prefixes listed in ascii form
606     * side effects - NONE
607     */
608     static const char *
609 michael 6506 show_iline_prefix(const struct Client *source_p, const struct MaskItem *conf)
610 michael 1372 {
611 michael 7460 static char buf[USERLEN + 16];
612     char *p = buf;
613 michael 1372
614 michael 1715 if (IsConfWebIRC(conf))
615 michael 7460 *p++ = '<';
616 michael 1632 if (IsNoTilde(conf))
617 michael 7460 *p++ = '-';
618 michael 1632 if (IsNeedIdentd(conf))
619 michael 7460 *p++ = '+';
620 michael 1632 if (!IsNeedPassword(conf))
621 michael 7460 *p++ = '&';
622 michael 1632 if (IsConfExemptResv(conf))
623 michael 7460 *p++ = '$';
624 michael 1632 if (IsConfDoSpoofIp(conf))
625 michael 7460 *p++ = '=';
626     if (IsConfCanFlood(conf))
627     *p++ = '|';
628 michael 6506 if (HasUMode(source_p, UMODE_OPER))
629     {
630     if (IsConfExemptKline(conf))
631 michael 7460 *p++ = '^';
632 michael 6506 if (IsConfExemptXline(conf))
633 michael 7460 *p++ = '!';
634 michael 6506 if (IsConfExemptLimits(conf))
635 michael 7460 *p++ = '>';
636 michael 6506 }
637    
638 michael 7511 strlcpy(p, conf->user, USERLEN + 1);
639 michael 7460 return buf;
640 michael 1372 }
641    
642 adx 30 static void
643 michael 3156 report_auth(struct Client *source_p, int parc, char *parv[])
644 michael 1372 {
645 michael 7687 dlink_node *node;
646 michael 1372
647 michael 3246 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
648 michael 1372 {
649 michael 4815 DLINK_FOREACH(node, atable[i].head)
650 michael 1372 {
651 michael 4815 const struct AddressRec *arec = node->data;
652 michael 1372
653 michael 1632 if (arec->type != CONF_CLIENT)
654     continue;
655 michael 1372
656 michael 7471 const struct MaskItem *conf = arec->conf;
657 michael 6506 if (!HasUMode(source_p, UMODE_OPER) && IsConfDoSpoofIp(conf))
658 michael 1632 continue;
659 michael 1372
660 michael 4967 sendto_one_numeric(source_p, &me, RPL_STATSILINE, 'I',
661     conf->name == NULL ? "*" : conf->name,
662     show_iline_prefix(source_p, conf),
663     conf->host, conf->port,
664     conf->class->name);
665 michael 1372 }
666     }
667     }
668    
669     static void
670 michael 1457 stats_auth(struct Client *source_p, int parc, char *parv[])
671 adx 30 {
672     /* Oper only, if unopered, return ERR_NOPRIVILEGES */
673 michael 4340 if (ConfigGeneral.stats_i_oper_only == 2 && !HasUMode(source_p, UMODE_OPER))
674 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
675 adx 30
676 michael 4034 /* If unopered, only return matching auth blocks */
677 michael 4340 else if (ConfigGeneral.stats_i_oper_only == 1 && !HasUMode(source_p, UMODE_OPER))
678 adx 30 {
679 michael 4034 const struct MaskItem *conf = NULL;
680 adx 30
681     if (MyConnect(source_p))
682 michael 1632 conf = find_conf_by_address(source_p->host,
683 michael 4588 &source_p->connection->ip, CONF_CLIENT,
684     source_p->connection->aftype,
685 michael 2820 source_p->username,
686 michael 4588 source_p->connection->password, 1);
687 adx 30 else
688 michael 4034 conf = find_conf_by_address(source_p->host, NULL, CONF_CLIENT, 0,
689     source_p->username, NULL, 1);
690 adx 30
691 michael 7471 if (!conf)
692 adx 30 return;
693    
694 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSILINE,
695     'I', "*", show_iline_prefix(source_p, conf),
696     conf->host, conf->port,
697 michael 4037 conf->class->name);
698 adx 30 }
699 michael 4034 else /* They are opered, or allowed to see all auth blocks */
700 michael 1457 report_auth(source_p, 0, NULL);
701 adx 30 }
702    
703 michael 1372 /* report_Klines()
704     * Inputs: Client to report to,
705     * type(==0 for perm, !=0 for temporary)
706 michael 2820 * mask
707 michael 1372 * Output: None
708 michael 3156 * Side effects: Reports configured K(or k)-lines to source_p.
709 michael 1372 */
710 adx 30 static void
711 michael 3156 report_Klines(struct Client *source_p, int tkline)
712 michael 1372 {
713 michael 7687 dlink_node *node;
714 michael 1921 char c = '\0';
715 michael 1372
716     if (tkline)
717 michael 1921 c = 'k';
718 michael 1372 else
719 michael 1921 c = 'K';
720 michael 1372
721 michael 3246 for (unsigned int i = 0; i < ATABLE_SIZE; ++i)
722 michael 1372 {
723 michael 4815 DLINK_FOREACH(node, atable[i].head)
724 michael 1372 {
725 michael 4815 const struct AddressRec *arec = node->data;
726 michael 1372
727 michael 1632 if (arec->type != CONF_KLINE)
728     continue;
729 michael 1628
730 michael 7471 const struct MaskItem *conf = arec->conf;
731 michael 1650 if ((!tkline && conf->until) ||
732     (tkline && !conf->until))
733 michael 1632 continue;
734    
735 michael 4570 sendto_one_numeric(source_p, &me, RPL_STATSKLINE, c, conf->host, conf->user,
736     conf->reason);
737 michael 1372 }
738     }
739     }
740    
741     static void
742 michael 1457 stats_tklines(struct Client *source_p, int parc, char *parv[])
743 adx 30 {
744     /* Oper only, if unopered, return ERR_NOPRIVILEGES */
745 michael 4340 if (ConfigGeneral.stats_k_oper_only == 2 && !HasUMode(source_p, UMODE_OPER))
746 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
747 adx 30
748 michael 4034 /* If unopered, only return matching klines */
749 michael 4340 else if (ConfigGeneral.stats_k_oper_only == 1 && !HasUMode(source_p, UMODE_OPER))
750 adx 30 {
751 michael 4032 const struct MaskItem *conf = NULL;
752 adx 30
753     if (MyConnect(source_p))
754 michael 1632 conf = find_conf_by_address(source_p->host,
755 michael 4588 &source_p->connection->ip, CONF_KLINE,
756     source_p->connection->aftype,
757 michael 2820 source_p->username, NULL, 1);
758 adx 30 else
759 michael 4034 conf = find_conf_by_address(source_p->host, NULL, CONF_KLINE, 0,
760     source_p->username, NULL, 1);
761 adx 30
762 michael 1632 if (!conf)
763 adx 30 return;
764    
765 michael 5542 /* Don't report a permanent kline as temporary kline */
766 michael 1649 if (!conf->until)
767 adx 30 return;
768    
769 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSKLINE, 'k',
770     conf->host, conf->user, conf->reason);
771 adx 30 }
772 michael 4034 else /* They are opered, or allowed to see all klines */
773 adx 30 report_Klines(source_p, 1);
774     }
775    
776     static void
777 michael 1457 stats_klines(struct Client *source_p, int parc, char *parv[])
778 adx 30 {
779     /* Oper only, if unopered, return ERR_NOPRIVILEGES */
780 michael 4340 if (ConfigGeneral.stats_k_oper_only == 2 && !HasUMode(source_p, UMODE_OPER))
781 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
782 adx 30
783 michael 4034 /* If unopered, only return matching klines */
784 michael 4340 else if (ConfigGeneral.stats_k_oper_only == 1 && !HasUMode(source_p, UMODE_OPER))
785 adx 30 {
786 michael 4032 const struct MaskItem *conf = NULL;
787 adx 30
788 michael 4034 /* Search for a kline */
789 michael 560 if (MyConnect(source_p))
790 michael 1632 conf = find_conf_by_address(source_p->host,
791 michael 4588 &source_p->connection->ip, CONF_KLINE,
792     source_p->connection->aftype,
793 michael 2820 source_p->username, NULL, 0);
794 adx 30 else
795 michael 4034 conf = find_conf_by_address(source_p->host, NULL, CONF_KLINE, 0,
796     source_p->username, NULL, 0);
797 adx 30
798 michael 1632 if (!conf)
799 adx 30 return;
800    
801 michael 5542 /* Don't report a temporary kline as permanent kline */
802 michael 1649 if (conf->until)
803 adx 30 return;
804 michael 2820
805 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSKLINE, 'K',
806     conf->host, conf->user, conf->reason);
807 adx 30 }
808 michael 4034 else /* They are opered, or allowed to see all klines */
809 adx 30 report_Klines(source_p, 0);
810     }
811    
812     static void
813 michael 1457 stats_messages(struct Client *source_p, int parc, char *parv[])
814 adx 30 {
815 michael 5026 if (!HasUMode(source_p, UMODE_OPER) && ConfigGeneral.stats_m_oper_only)
816     sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
817     else
818     report_messages(source_p);
819 adx 30 }
820    
821     /* stats_operedup()
822     *
823     * input - client pointer
824     * output - none
825     * side effects - client is shown a list of active opers
826     */
827     static void
828 michael 1457 stats_operedup(struct Client *source_p, int parc, char *parv[])
829 adx 30 {
830 michael 7687 dlink_node *node;
831 michael 3511 unsigned int opercount = 0;
832 michael 3516 char buf[IRCD_BUFSIZE] = "";
833 adx 30
834 michael 4815 DLINK_FOREACH(node, oper_list.head)
835 adx 30 {
836 michael 4815 const struct Client *target_p = node->data;
837 adx 30
838 michael 1294 if (HasUMode(target_p, UMODE_HIDDEN) && !HasUMode(source_p, UMODE_OPER))
839 adx 30 continue;
840    
841 michael 3516 if (HasUMode(source_p, UMODE_OPER) || !HasUMode(target_p, UMODE_HIDEIDLE))
842 michael 6846 snprintf(buf, sizeof(buf), "%s", time_dissect(client_get_idle_time(source_p, target_p)));
843 michael 3516 else
844     strlcpy(buf, "n/a", sizeof(buf));
845    
846 michael 7051 if (MyConnect(source_p) && HasUMode(source_p, UMODE_OPER))
847 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
848 michael 3573 "p :[%c][%s] %s (%s@%s) Idle: %s",
849     HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O',
850 michael 4588 oper_privs_as_string(target_p->connection->operflags),
851 michael 3573 target_p->name, target_p->username, target_p->host, buf);
852 adx 30 else
853 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
854 michael 3573 "p :[%c] %s (%s@%s) Idle: %s",
855     HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O',
856     target_p->name, target_p->username, target_p->host, buf);
857 michael 3511 ++opercount;
858 adx 30 }
859    
860 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
861 michael 3573 "p :%u OPER(s)", opercount);
862 adx 30 }
863    
864 michael 6366 /* show_ports()
865     *
866     * inputs - pointer to client to show ports to
867     * output - none
868     * side effects - send port listing to a client
869     */
870 adx 30 static void
871 michael 6366 show_ports(struct Client *source_p)
872     {
873 michael 7687 dlink_node *node;
874 michael 6366
875     DLINK_FOREACH(node, listener_get_list()->head)
876     {
877 michael 7687 char buf[8];
878     char *p = buf;
879 michael 6366 const struct Listener *listener = node->data;
880    
881     if (listener->flags & LISTENER_HIDDEN)
882     {
883     if (!HasUMode(source_p, UMODE_ADMIN))
884     continue;
885     *p++ = 'H';
886     }
887    
888     if (listener->flags & LISTENER_SERVER)
889     *p++ = 'S';
890     if (listener->flags & LISTENER_SSL)
891     *p++ = 's';
892     *p = '\0';
893    
894 michael 7656 if (HasUMode(source_p, UMODE_ADMIN) && !ConfigServerHide.hide_server_ips)
895 michael 6366 sendto_one_numeric(source_p, &me, RPL_STATSPLINE, 'P', listener->port,
896     listener->name,
897     listener->ref_count, buf,
898     listener->active ? "active" : "disabled");
899     else
900     sendto_one_numeric(source_p, &me, RPL_STATSPLINE, 'P', listener->port,
901     me.name, listener->ref_count, buf,
902     listener->active ? "active" : "disabled");
903     }
904     }
905    
906     static void
907 michael 1457 stats_ports(struct Client *source_p, int parc, char *parv[])
908 adx 30 {
909 michael 4340 if (!HasUMode(source_p, UMODE_OPER) && ConfigGeneral.stats_P_oper_only)
910 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
911 adx 30 else
912     show_ports(source_p);
913     }
914    
915     static void
916 michael 1457 stats_tstats(struct Client *source_p, int parc, char *parv[])
917 adx 30 {
918 michael 7687 dlink_node *node;
919 michael 896 struct ServerStatistics tmp;
920 michael 1842 struct ServerStatistics *sp = &tmp;
921 michael 896
922     memcpy(sp, &ServerStats, sizeof(struct ServerStatistics));
923    
924     /*
925     * must use the += operator. is_sv is not the number of currently
926     * active server connections. Note the incrementation in
927     * s_bsd.c:close_connection.
928     */
929 michael 4213 sp->is_sv += dlink_list_length(&local_server_list);
930 michael 896
931 michael 4815 DLINK_FOREACH(node, local_server_list.head)
932 michael 896 {
933 michael 4815 const struct Client *target_p = node->data;
934 michael 896
935 michael 4588 sp->is_sbs += target_p->connection->send.bytes;
936     sp->is_sbr += target_p->connection->recv.bytes;
937     sp->is_sti += CurrentTime - target_p->connection->firsttime;
938 michael 896 }
939    
940     sp->is_cl += dlink_list_length(&local_client_list);
941    
942 michael 4815 DLINK_FOREACH(node, local_client_list.head)
943 michael 896 {
944 michael 4815 const struct Client *target_p = node->data;
945 michael 896
946 michael 4588 sp->is_cbs += target_p->connection->send.bytes;
947     sp->is_cbr += target_p->connection->recv.bytes;
948     sp->is_cti += CurrentTime - target_p->connection->firsttime;
949 michael 896 }
950    
951     sp->is_ni += dlink_list_length(&unknown_list);
952    
953 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
954 michael 4040 "t :accepts %u refused %u",
955 michael 3573 sp->is_ac, sp->is_ref);
956 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
957 michael 4040 "t :unknown commands %u prefixes %u",
958 michael 3573 sp->is_unco, sp->is_unpf);
959 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
960 michael 4040 "t :nick collisions %u unknown closes %u",
961 michael 3573 sp->is_kill, sp->is_ni);
962 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
963 michael 4040 "t :wrong direction %u empty %u",
964 michael 3573 sp->is_wrdi, sp->is_empt);
965 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
966 michael 4040 "t :numerics seen %u",
967 michael 3573 sp->is_num);
968 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
969 michael 4040 "t :auth successes %u fails %u",
970 michael 3573 sp->is_asuc, sp->is_abad);
971 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
972 michael 4040 "t :Client Server");
973 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
974 michael 4040 "t :connected %u %u",
975 michael 7330 sp->is_cl, sp->is_sv);
976 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
977 michael 6782 "t :bytes sent %ju %ju",
978 michael 3573 sp->is_cbs, sp->is_sbs);
979 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
980 michael 7471 "t :bytes received %ju %ju",
981 michael 3573 sp->is_cbr, sp->is_sbr);
982 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
983 michael 7330 "t :time connected %ju %ju",
984     sp->is_cti, sp->is_sti);
985 adx 30 }
986    
987     static void
988 michael 1457 stats_uptime(struct Client *source_p, int parc, char *parv[])
989 adx 30 {
990 michael 4340 if (!HasUMode(source_p, UMODE_OPER) && ConfigGeneral.stats_u_oper_only)
991 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
992 michael 2269 else
993     {
994 michael 6569 sendto_one_numeric(source_p, &me, RPL_STATSUPTIME,
995     time_dissect(CurrentTime - me.connection->since));
996 michael 2269 if (!ConfigServerHide.disable_remote_commands || HasUMode(source_p, UMODE_OPER))
997 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSCONN, Count.max_loc_con,
998     Count.max_loc_cli, Count.totalrestartcount);
999 michael 2269 }
1000 adx 30 }
1001    
1002     static void
1003 michael 1457 stats_shared(struct Client *source_p, int parc, char *parv[])
1004 adx 30 {
1005 michael 7209 report_shared(source_p);
1006     report_cluster(source_p);
1007 adx 30 }
1008    
1009     /* stats_servers()
1010     *
1011     * input - client pointer
1012     * output - none
1013     * side effects - client is shown lists of who connected servers
1014     */
1015     static void
1016 michael 1457 stats_servers(struct Client *source_p, int parc, char *parv[])
1017 adx 30 {
1018 michael 7687 dlink_node *node;
1019 adx 30
1020 michael 4815 DLINK_FOREACH(node, local_server_list.head)
1021 adx 30 {
1022 michael 4815 const struct Client *target_p = node->data;
1023 adx 30
1024 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1025 michael 6846 "v :%s (%s!%s@%s) Idle: %s",
1026 michael 3573 target_p->name,
1027     (target_p->serv->by[0] ? target_p->serv->by : "Remote."),
1028 michael 6846 "*", "*", time_dissect(CurrentTime - target_p->connection->lasttime));
1029 adx 30 }
1030    
1031 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1032 michael 4213 "v :%u Server(s)",
1033     dlink_list_length(&local_server_list));
1034 adx 30 }
1035    
1036     static void
1037 michael 1457 stats_class(struct Client *source_p, int parc, char *parv[])
1038 adx 30 {
1039 michael 7914 dlink_node *node;
1040 michael 2116
1041 michael 4815 DLINK_FOREACH(node, class_get_list()->head)
1042 michael 2116 {
1043 michael 4815 const struct ClassItem *class = node->data;
1044 michael 2116
1045 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSYLINE, 'Y',
1046     class->name, class->ping_freq,
1047     class->con_freq,
1048     class->max_total, class->max_sendq,
1049     class->max_recvq,
1050     class->ref_count,
1051     class->number_per_cidr, class->cidr_bitlen_ipv4,
1052     class->number_per_cidr, class->cidr_bitlen_ipv6,
1053     class->active ? "active" : "disabled");
1054 michael 2116 }
1055 adx 30 }
1056    
1057     static void
1058 michael 1457 stats_servlinks(struct Client *source_p, int parc, char *parv[])
1059 adx 30 {
1060 michael 7471 dlink_node *node;
1061 michael 6782 uintmax_t sendB = 0, recvB = 0;
1062 michael 7330 uintmax_t uptime = 0;
1063 adx 30
1064 michael 1219 if (ConfigServerHide.flatten_links && !HasUMode(source_p, UMODE_OPER))
1065 adx 30 {
1066 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
1067 adx 30 return;
1068     }
1069    
1070 michael 4815 DLINK_FOREACH(node, local_server_list.head)
1071 adx 30 {
1072 michael 7471 const struct Client *target_p = node->data;
1073 adx 30
1074 michael 1851 if (HasFlag(target_p, FLAGS_SERVICE) && ConfigServerHide.hide_services)
1075     if (!HasUMode(source_p, UMODE_OPER))
1076     continue;
1077    
1078 michael 4588 sendB += target_p->connection->send.bytes;
1079     recvB += target_p->connection->recv.bytes;
1080 adx 30
1081 michael 6782 /* ":%s 211 %s %s %u %u %ju %u %ju :%u %u %s" */
1082 michael 3109 sendto_one_numeric(source_p, &me, RPL_STATSLINKINFO,
1083 michael 1219 get_client_name(target_p, HasUMode(source_p, UMODE_ADMIN) ? SHOW_IP : MASK_IP),
1084 michael 4588 dbuf_length(&target_p->connection->buf_sendq),
1085     target_p->connection->send.messages,
1086     target_p->connection->send.bytes >> 10,
1087     target_p->connection->recv.messages,
1088     target_p->connection->recv.bytes >> 10,
1089 michael 5531 (unsigned int)(CurrentTime - target_p->connection->firsttime),
1090     (CurrentTime > target_p->connection->since) ? (unsigned int)(CurrentTime - target_p->connection->since) : 0,
1091 michael 7590 HasUMode(source_p, UMODE_OPER) ? get_capabilities(target_p) : "TS");
1092 adx 30 }
1093    
1094     sendB >>= 10;
1095     recvB >>= 10;
1096    
1097 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT, "? :%u total server(s)",
1098 michael 4213 dlink_list_length(&local_server_list));
1099 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT, "? :Sent total: %7.2f %s",
1100 michael 3573 _GMKv(sendB), _GMKs(sendB));
1101 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT, "? :Recv total: %7.2f %s",
1102 michael 3573 _GMKv(recvB), _GMKs(recvB));
1103 adx 30
1104 michael 4588 uptime = (CurrentTime - me.connection->since);
1105 adx 30
1106 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1107 michael 3573 "? :Server send: %7.2f %s (%4.1f K/s)",
1108 michael 7382 _GMKv((me.connection->send.bytes >> 10)),
1109     _GMKs((me.connection->send.bytes >> 10)),
1110 michael 4588 (float)((float)((me.connection->send.bytes) >> 10) /
1111 michael 3573 (float)uptime));
1112 michael 5583 sendto_one_numeric(source_p, &me, RPL_STATSDEBUG | SND_EXPLICIT,
1113 michael 3573 "? :Server recv: %7.2f %s (%4.1f K/s)",
1114 michael 7382 _GMKv((me.connection->recv.bytes >> 10)),
1115     _GMKs((me.connection->recv.bytes >> 10)),
1116 michael 4588 (float)((float)((me.connection->recv.bytes) >> 10) /
1117 michael 3573 (float)uptime));
1118 adx 30 }
1119    
1120 michael 1457 /* parse_stats_args()
1121     *
1122     * inputs - arg count
1123     * - args
1124     * - doall flag
1125     * - wild card or not
1126     * output - pointer to name to use
1127     * side effects -
1128     * common parse routine for m_stats args
1129 michael 2820 *
1130 michael 1457 */
1131 michael 4755 static const char *
1132 michael 3114 parse_stats_args(struct Client *source_p, int parc, char *parv[], int *doall, int *wilds)
1133 adx 30 {
1134 michael 1457 if (parc > 2)
1135 adx 30 {
1136 michael 4755 const char *name = parv[2];
1137 adx 30
1138 michael 3114 if (!irccmp(name, ID_or_name(&me, source_p)))
1139 michael 1457 *doall = 2;
1140 michael 3114 else if (!match(name, ID_or_name(&me, source_p)))
1141 michael 1457 *doall = 1;
1142    
1143     *wilds = has_wildcards(name);
1144    
1145     return name;
1146 adx 30 }
1147    
1148 michael 1457 return NULL;
1149 adx 30 }
1150    
1151     static void
1152 michael 4755 stats_L_list(struct Client *source_p, const char *name, int doall, int wilds,
1153     dlink_list *list, const char statchar)
1154 adx 30 {
1155 michael 7471 dlink_node *node;
1156 adx 30
1157     /*
1158 michael 4034 * Send info about connections which match, or all if the
1159 michael 7652 * mask matches from.
1160 adx 30 */
1161 michael 4815 DLINK_FOREACH(node, list->head)
1162 adx 30 {
1163 michael 7471 const struct Client *target_p = node->data;
1164 michael 7652 enum addr_mask_type type = 0;
1165 adx 30
1166 michael 1652 if (!doall && wilds && match(name, target_p->name))
1167 adx 30 continue;
1168 michael 4034
1169 adx 30 if (!(doall || wilds) && irccmp(name, target_p->name))
1170     continue;
1171    
1172 michael 7652 if (IsUpper(statchar))
1173     type = SHOW_IP;
1174 adx 30 else
1175 michael 7652 type = HIDE_IP;
1176    
1177     if (IsServer(target_p) || IsConnecting(target_p) || IsHandshake(target_p))
1178 michael 7654 if (!HasUMode(source_p, UMODE_ADMIN))
1179 michael 7652 type = MASK_IP;
1180    
1181     sendto_one_numeric(source_p, &me, RPL_STATSLINKINFO,
1182     get_client_name(target_p, type),
1183     dbuf_length(&target_p->connection->buf_sendq),
1184     target_p->connection->send.messages,
1185     target_p->connection->send.bytes >> 10,
1186     target_p->connection->recv.messages,
1187     target_p->connection->recv.bytes >> 10,
1188     (unsigned int)(CurrentTime - target_p->connection->firsttime),
1189     (CurrentTime > target_p->connection->since) ? (unsigned int)(CurrentTime - target_p->connection->since) : 0,
1190     IsServer(target_p) ? get_capabilities(target_p) : "-");
1191 adx 30 }
1192     }
1193    
1194 michael 1457 /*
1195     * stats_L
1196 adx 30 *
1197 michael 1457 * inputs - pointer to client to report to
1198     * - doall flag
1199     * - wild card or not
1200     * output - NONE
1201     * side effects -
1202     */
1203     static void
1204 michael 4755 stats_L(struct Client *source_p, const char *name, int doall,
1205     int wilds, const char statchar)
1206 michael 1457 {
1207     stats_L_list(source_p, name, doall, wilds, &unknown_list, statchar);
1208     stats_L_list(source_p, name, doall, wilds, &local_client_list, statchar);
1209 michael 4213 stats_L_list(source_p, name, doall, wilds, &local_server_list, statchar);
1210 michael 1457 }
1211    
1212     static void
1213     stats_ltrace(struct Client *source_p, int parc, char *parv[])
1214     {
1215     int doall = 0;
1216     int wilds = 0;
1217 michael 4755 const char *name = NULL;
1218 michael 1457
1219 michael 3246 if ((name = parse_stats_args(source_p, parc, parv, &doall, &wilds)))
1220 michael 1457 {
1221 michael 4755 const char statchar = *parv[1];
1222 michael 1457 stats_L(source_p, name, doall, wilds, statchar);
1223     }
1224     else
1225 michael 3109 sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "STATS");
1226 michael 1457 }
1227    
1228 michael 6552 struct StatsStruct
1229 michael 1457 {
1230     const unsigned char letter;
1231 michael 4479 void (*handler)(struct Client *, int, char *[]);
1232 michael 6552 const unsigned int required_modes;
1233 michael 1457 };
1234    
1235 michael 6552 static const struct StatsStruct *stats_map[256];
1236     static const struct StatsStruct stats_tab[] =
1237     {
1238     { 'a', stats_dns_servers, UMODE_ADMIN },
1239     { 'A', stats_dns_servers, UMODE_ADMIN },
1240     { 'c', stats_connect, UMODE_OPER },
1241     { 'C', stats_connect, UMODE_OPER },
1242     { 'd', stats_tdeny, UMODE_OPER },
1243     { 'D', stats_deny, UMODE_OPER },
1244     { 'e', stats_exempt, UMODE_OPER },
1245     { 'E', stats_events, UMODE_ADMIN },
1246     { 'f', fd_dump, UMODE_ADMIN },
1247     { 'F', fd_dump, UMODE_ADMIN },
1248     { 'h', stats_hubleaf, UMODE_OPER },
1249     { 'H', stats_hubleaf, UMODE_OPER },
1250     { 'i', stats_auth, 0 },
1251     { 'I', stats_auth, 0 },
1252     { 'k', stats_tklines, 0 },
1253     { 'K', stats_klines, 0 },
1254     { 'l', stats_ltrace, UMODE_OPER },
1255     { 'L', stats_ltrace, UMODE_OPER },
1256     { 'm', stats_messages, 0 },
1257     { 'M', stats_messages, 0 },
1258 michael 7405 { 'o', stats_operator, 0 },
1259     { 'O', stats_operator, 0 },
1260 michael 6552 { 'p', stats_operedup, 0 },
1261     { 'P', stats_ports, 0 },
1262     { 'q', stats_resv, UMODE_OPER },
1263     { 'Q', stats_resv, UMODE_OPER },
1264     { 's', stats_service, UMODE_OPER },
1265     { 'S', stats_service, UMODE_OPER },
1266     { 't', stats_tstats, UMODE_OPER },
1267     { 'T', motd_report, UMODE_OPER },
1268     { 'u', stats_uptime, 0 },
1269     { 'U', stats_shared, UMODE_OPER },
1270     { 'v', stats_servers, UMODE_OPER },
1271     { 'x', stats_gecos, UMODE_OPER },
1272     { 'X', stats_gecos, UMODE_OPER },
1273     { 'y', stats_class, UMODE_OPER },
1274     { 'Y', stats_class, UMODE_OPER },
1275     { 'z', stats_memory, UMODE_OPER },
1276     { '?', stats_servlinks, 0 },
1277     { '\0', NULL, 0 }
1278     };
1279    
1280 michael 1457 static void
1281     do_stats(struct Client *source_p, int parc, char *parv[])
1282     {
1283 michael 6552 const unsigned char statchar = *parv[1];
1284     const struct StatsStruct *tab;
1285 michael 1457
1286     if (statchar == '\0')
1287     {
1288 michael 3109 sendto_one_numeric(source_p, &me, RPL_ENDOFSTATS, '*');
1289 michael 1457 return;
1290     }
1291    
1292 michael 6552 if ((tab = stats_map[statchar]))
1293 michael 1457 {
1294 michael 6552 if (!tab->required_modes || HasUMode(source_p, tab->required_modes))
1295     tab->handler(source_p, parc, parv);
1296     else
1297     sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
1298 michael 1457
1299 michael 6552 sendto_realops_flags(UMODE_SPY, L_ALL, SEND_NOTICE,
1300     "STATS %c requested by %s (%s@%s) [%s]",
1301     statchar, source_p->name, source_p->username,
1302     source_p->host, source_p->servptr->name);
1303 michael 1457 }
1304    
1305 michael 3109 sendto_one_numeric(source_p, &me, RPL_ENDOFSTATS, statchar);
1306 michael 1457 }
1307    
1308     /*
1309     * m_stats()
1310 michael 3096 * parv[0] = command
1311 michael 1457 * parv[1] = stat letter/command
1312     * parv[2] = (if present) server/mask in stats L
1313 adx 30 */
1314 michael 2820 static int
1315 michael 3156 m_stats(struct Client *source_p, int parc, char *parv[])
1316 adx 30 {
1317 michael 7330 static uintmax_t last_used = 0;
1318 adx 30
1319 michael 4298 /* Check the user is actually allowed to do /stats, and isn't flooding */
1320 michael 4340 if ((last_used + ConfigGeneral.pace_wait) > CurrentTime)
1321 michael 1457 {
1322 michael 4759 sendto_one_numeric(source_p, &me, RPL_LOAD2HI, "STATS");
1323 michael 2820 return 0;
1324 michael 1457 }
1325 adx 30
1326 michael 1457 last_used = CurrentTime;
1327 adx 30
1328 michael 2341 /* Is the stats meant for us? */
1329     if (!ConfigServerHide.disable_remote_commands)
1330 michael 7953 if (server_hunt(source_p, ":%s STATS %s :%s", 2, parc, parv) != HUNTED_ISME)
1331 michael 2820 return 0;
1332 michael 2341
1333 michael 1457 do_stats(source_p, parc, parv);
1334 michael 2820 return 0;
1335 michael 1457 }
1336    
1337     /*
1338 michael 3219 * ms_stats()
1339 michael 3096 * parv[0] = command
1340 michael 1457 * parv[1] = stat letter/command
1341     * parv[2] = (if present) server/mask in stats L, or target
1342     */
1343 michael 2820 static int
1344 michael 3219 ms_stats(struct Client *source_p, int parc, char *parv[])
1345 michael 1457 {
1346 michael 7953 if (server_hunt(source_p, ":%s STATS %s :%s", 2, parc, parv) != HUNTED_ISME)
1347 michael 2820 return 0;
1348 michael 1457
1349     do_stats(source_p, parc, parv);
1350 michael 2820 return 0;
1351 adx 30 }
1352 michael 1230
1353 michael 6552 static void
1354     stats_init(void)
1355     {
1356     for (const struct StatsStruct *tab = stats_tab; tab->letter; ++tab)
1357     stats_map[tab->letter] = tab;
1358     }
1359    
1360 michael 2820 static struct Message stats_msgtab =
1361     {
1362 michael 5881 .cmd = "STATS",
1363     .args_min = 2,
1364     .args_max = MAXPARA,
1365     .handlers[UNREGISTERED_HANDLER] = m_unregistered,
1366     .handlers[CLIENT_HANDLER] = m_stats,
1367     .handlers[SERVER_HANDLER] = ms_stats,
1368     .handlers[ENCAP_HANDLER] = m_ignore,
1369     .handlers[OPER_HANDLER] = ms_stats
1370 michael 1230 };
1371    
1372     static void
1373     module_init(void)
1374     {
1375 michael 6552 stats_init();
1376 michael 1230 mod_add_cmd(&stats_msgtab);
1377     }
1378    
1379     static void
1380     module_exit(void)
1381     {
1382     mod_del_cmd(&stats_msgtab);
1383     }
1384    
1385 michael 2820 struct module module_entry =
1386     {
1387 michael 1230 .version = "$Revision$",
1388     .modinit = module_init,
1389     .modexit = module_exit,
1390     };

Properties

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