ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/m_stats.c
Revision: 7510
Committed: Sat Mar 26 19:48:19 2016 UTC (9 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 45359 byte(s)
Log Message:
- m_stats.c:show_iline_prefix(): whitespace change

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

Properties

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