ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_stats.c
Revision: 9318
Committed: Sun Mar 8 11:40:39 2020 UTC (4 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 45762 byte(s)
Log Message:
- m_stats.c:stats_dns_servers(): remove extraneous parantheses on irc_nsaddr_list

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

Properties

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