ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_stats.c
Revision: 9101
Committed: Wed Jan 1 09:58:45 2020 UTC (4 years, 2 months ago) by michael
Content type: text/x-csrc
File size: 45741 byte(s)
Log Message:
- Bump copyright years everywhere

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

Properties

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