ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_stats.c
Revision: 8923
Committed: Mon Apr 22 10:09:22 2019 UTC (4 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 43404 byte(s)
Log Message:
- Use proper conversion specifiers in some places; remove pointless casts

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

Properties

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