ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_stats.c
Revision: 8310
Committed: Wed Feb 28 16:46:13 2018 UTC (6 years ago) by michael
Content type: text/x-csrc
File size: 43028 byte(s)
Log Message:
- Clean up remaining sizeof() to sizeof(variable)

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

Properties

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