/[svn]/branches/newio/modules/m_stats.c
ViewVC logotype

Contents of /branches/newio/modules/m_stats.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2692 - (show annotations)
Tue Dec 17 18:56:15 2013 UTC (8 years, 8 months ago) by michael
File MIME type: text/x-chdr
File size: 52928 byte(s)
- Avoid magically sized temporary buffers

1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * m_stats.c: Sends the user statistics or config information.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "list.h" /* dlink_node/dlink_list */
27 #include "client.h" /* Client */
28 #include "irc_string.h"
29 #include "ircd.h" /* me */
30 #include "listener.h" /* show_ports */
31 #include "s_gline.h"
32 #include "conf.h"
33 #include "conf_class.h"
34 #include "hostmask.h"
35 #include "numeric.h" /* ERR_xxx */
36 #include "send.h" /* sendto_one */
37 #include "s_bsd.h" /* highest_fd */
38 #include "s_misc.h" /* serv_info */
39 #include "s_serv.h" /* hunt_server */
40 #include "s_user.h" /* show_opers */
41 #include "dbuf.h"
42 #include "hook.h"
43 #include "parse.h"
44 #include "modules.h"
45 #include "resv.h" /* report_resv */
46 #include "whowas.h"
47 #include "watch.h"
48 #include "irc_res.h"
49 #include "motd.h"
50 #include "msgq.h"
51 #include "ioengine.h"
52
53
54 const char *from, *to;
55
56 static const struct shared_flags
57 {
58 const unsigned int type;
59 const unsigned char letter;
60 } flag_table[] = {
61 { SHARED_KLINE, 'K' },
62 { SHARED_UNKLINE, 'U' },
63 { SHARED_XLINE, 'X' },
64 { SHARED_UNXLINE, 'Y' },
65 { SHARED_RESV, 'Q' },
66 { SHARED_UNRESV, 'R' },
67 { SHARED_LOCOPS, 'L' },
68 { SHARED_DLINE, 'D' },
69 { SHARED_UNDLINE, 'E' },
70 { 0, '\0' }
71 };
72
73 /*
74 * inputs - pointer to client requesting confitem report
75 * - ConfType to report
76 * output - none
77 * side effects -
78 */
79 static void
80 report_confitem_types(struct Client *source_p, enum maskitem_type type)
81 {
82 dlink_node *ptr = NULL;
83 struct MaskItem *conf = NULL;
84 const struct shared_flags *shared = NULL;
85 char buf[IRCD_BUFSIZE];
86 char *p = NULL;
87
88 switch (type)
89 {
90 case CONF_XLINE:
91 DLINK_FOREACH(ptr, xconf_items.head)
92 {
93 conf = ptr->data;
94
95 sendto_one(source_p, form_str(RPL_STATSXLINE),
96 me.name, source_p->name,
97 conf->until ? 'x': 'X', conf->count,
98 conf->name, conf->reason);
99 }
100 break;
101
102 case CONF_ULINE:
103 shared = flag_table;
104 DLINK_FOREACH(ptr, uconf_items.head)
105 {
106 conf = ptr->data;
107
108 p = buf;
109
110 *p++ = 'c';
111 for (; shared->type; ++shared)
112 if (shared->type & conf->flags)
113 *p++ = shared->letter;
114 else
115 *p++ = ToLower(shared->letter);
116
117 sendto_one(source_p, form_str(RPL_STATSULINE),
118 me.name, source_p->name, conf->name,
119 conf->user?conf->user: "*",
120 conf->host?conf->host: "*", buf);
121 }
122
123 shared = flag_table;
124 DLINK_FOREACH(ptr, cluster_items.head)
125 {
126 conf = ptr->data;
127
128 p = buf;
129
130 *p++ = 'C';
131 for (; shared->type; ++shared)
132 if (shared->type & conf->flags)
133 *p++ = shared->letter;
134 else
135 *p++ = ToLower(shared->letter);
136
137 sendto_one(source_p, form_str(RPL_STATSULINE),
138 me.name, source_p->name, conf->name,
139 "*", "*", buf);
140 }
141
142 break;
143
144 case CONF_OPER:
145 DLINK_FOREACH(ptr, oconf_items.head)
146 {
147 conf = ptr->data;
148
149 /* Don't allow non opers to see oper privs */
150 if (HasUMode(source_p, UMODE_OPER))
151 sendto_one(source_p, form_str(RPL_STATSOLINE),
152 me.name, source_p->name, 'O', conf->count, conf->user, conf->host,
153 conf->name, oper_privs_as_string(conf->port),
154 conf->class ? conf->class->name : "<default>");
155 else
156 sendto_one(source_p, form_str(RPL_STATSOLINE),
157 me.name, source_p->name, 'O', conf->count, conf->user, conf->host,
158 conf->name, "0",
159 conf->class ? conf->class->name : "<default>");
160 }
161 break;
162
163 case CONF_SERVICE:
164 DLINK_FOREACH(ptr, service_items.head)
165 {
166 conf = ptr->data;
167 sendto_one(source_p, form_str(RPL_STATSSERVICE),
168 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
169 }
170 break;
171
172 case CONF_SERVER:
173 DLINK_FOREACH(ptr, server_items.head)
174 {
175 p = buf;
176 conf = ptr->data;
177
178 buf[0] = '\0';
179
180 if (IsConfAllowAutoConn(conf))
181 *p++ = 'A';
182 if (IsConfSSL(conf))
183 *p++ = 'S';
184 if (buf[0] == '\0')
185 *p++ = '*';
186
187 *p = '\0';
188
189 /*
190 * Allow admins to see actual ips unless hide_server_ips is enabled
191 */
192 if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
193 sendto_one(source_p, form_str(RPL_STATSCLINE),
194 me.name, source_p->name, 'C', conf->host,
195 buf, conf->name, conf->port,
196 conf->class ? conf->class->name : "<default>");
197 else
198 sendto_one(source_p, form_str(RPL_STATSCLINE),
199 me.name, source_p->name, 'C',
200 "*@127.0.0.1", buf, conf->name, conf->port,
201 conf->class ? conf->class->name : "<default>");
202 }
203 break;
204
205 default:
206 break;
207 }
208 }
209
210 /* report_resv()
211 *
212 * inputs - pointer to client pointer to report to.
213 * output - NONE
214 * side effects - report all resvs to client.
215 */
216 static void
217 report_resv(struct Client *source_p)
218 {
219 dlink_node *ptr = NULL;
220 struct MaskItem *conf = NULL;
221
222 DLINK_FOREACH(ptr, cresv_items.head)
223 {
224 conf = ptr->data;
225 sendto_one(source_p, form_str(RPL_STATSQLINE),
226 me.name, source_p->name,
227 conf->until ? 'q' : 'Q', conf->count,
228 conf->name, conf->reason);
229 }
230
231 DLINK_FOREACH(ptr, nresv_items.head)
232 {
233 conf = ptr->data;
234 sendto_one(source_p, form_str(RPL_STATSQLINE),
235 me.name, source_p->name,
236 conf->until ? 'q' : 'Q', conf->count,
237 conf->name, conf->reason);
238 }
239 }
240
241 /*
242 * This is part of the STATS replies. There is no offical numeric for this
243 * since this isnt an official command, in much the same way as HASH isnt.
244 * It is also possible that some systems wont support this call or have
245 * different field names for "struct rusage".
246 * -avalon
247 */
248 static void
249 stats_usage(struct Client *source_p, int parc, char *parv[])
250 {
251 struct rusage rus;
252 time_t secs;
253 time_t rup;
254 #ifdef hz
255 # define hzz hz
256 #else
257 # ifdef HZ
258 # define hzz HZ
259 # else
260 int hzz = 1;
261 # endif
262 #endif
263
264 if (getrusage(RUSAGE_SELF, &rus) == -1)
265 {
266 sendto_one(source_p, ":%s NOTICE %s :Getruseage error: %s",
267 me.name, source_p->name, strerror(errno));
268 return;
269 }
270
271 secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec;
272
273 if (secs == 0)
274 secs = 1;
275
276 rup = (CurrentTime - me.localClient->since) * hzz;
277
278 if (rup == 0)
279 rup = 1;
280
281 sendto_one(source_p,
282 ":%s %d %s R :CPU Secs %d:%02d User %d:%02d System %d:%02d",
283 me.name, RPL_STATSDEBUG, source_p->name, (int)(secs/60), (int)(secs%60),
284 (int)(rus.ru_utime.tv_sec/60), (int)(rus.ru_utime.tv_sec%60),
285 (int)(rus.ru_stime.tv_sec/60), (int)(rus.ru_stime.tv_sec%60));
286 sendto_one(source_p, ":%s %d %s R :RSS %ld ShMem %ld Data %ld Stack %ld",
287 me.name, RPL_STATSDEBUG, source_p->name, rus.ru_maxrss,
288 (rus.ru_ixrss / rup), (rus.ru_idrss / rup),
289 (rus.ru_isrss / rup));
290 sendto_one(source_p, ":%s %d %s R :Swaps %d Reclaims %d Faults %d",
291 me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_nswap,
292 (int)rus.ru_minflt, (int)rus.ru_majflt);
293 sendto_one(source_p, ":%s %d %s R :Block in %d out %d",
294 me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_inblock,
295 (int)rus.ru_oublock);
296 sendto_one(source_p, ":%s %d %s R :Msg Rcv %d Send %d",
297 me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_msgrcv,
298 (int)rus.ru_msgsnd);
299 sendto_one(source_p, ":%s %d %s R :Signals %d Context Vol. %d Invol %d",
300 me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_nsignals,
301 (int)rus.ru_nvcsw, (int)rus.ru_nivcsw);
302 }
303
304 static void
305 stats_memory(struct Client *source_p, int parc, char *parv[])
306 {
307 const dlink_node *gptr = NULL;
308 const dlink_node *dlink = NULL;
309
310 unsigned int local_client_conf_count = 0; /* local client conf links */
311 unsigned int users_counted = 0; /* user structs */
312
313 unsigned int channel_members = 0;
314 unsigned int channel_invites = 0;
315 unsigned int channel_bans = 0;
316 unsigned int channel_except = 0;
317 unsigned int channel_invex = 0;
318
319 unsigned int wwu = 0; /* whowas users */
320 unsigned int class_count = 0; /* classes */
321 unsigned int aways_counted = 0;
322 unsigned int number_ips_stored; /* number of ip addresses hashed */
323
324 uint64_t channel_memory = 0;
325 uint64_t channel_ban_memory = 0;
326 uint64_t channel_except_memory = 0;
327 uint64_t channel_invex_memory = 0;
328
329 uint64_t wwm = 0; /* whowas array memory used */
330 uint64_t conf_memory = 0; /* memory used by conf lines */
331 uint64_t mem_ips_stored; /* memory used by ip address hash */
332
333 uint64_t total_channel_memory = 0;
334 uint64_t totww = 0;
335
336 unsigned int local_client_count = 0;
337 unsigned int remote_client_count = 0;
338
339 uint64_t local_client_memory_used = 0;
340 uint64_t remote_client_memory_used = 0;
341
342 uint64_t total_memory = 0;
343 unsigned int topic_count = 0;
344
345 unsigned int watch_list_headers = 0; /* watchlist headers */
346 unsigned int watch_list_entries = 0; /* watchlist entries */
347 uint64_t watch_list_memory = 0; /* watchlist memory used */
348
349
350 DLINK_FOREACH(gptr, global_client_list.head)
351 {
352 struct Client *target_p = gptr->data;
353
354 if (MyConnect(target_p))
355 {
356 ++local_client_count;
357 local_client_conf_count += dlink_list_length(&target_p->localClient->confs);
358 watch_list_entries += dlink_list_length(&target_p->localClient->watches);
359 }
360 else
361 ++remote_client_count;
362
363 if (IsClient(target_p))
364 {
365 ++users_counted;
366
367 if (target_p->away[0])
368 ++aways_counted;
369 }
370 }
371
372 /* Count up all channels, ban lists, except lists, Invex lists */
373 channel_memory = dlink_list_length(&global_channel_list) *
374 sizeof(struct Channel);
375 DLINK_FOREACH(gptr, global_channel_list.head)
376 {
377 const struct Ban *actualBan;
378 const struct Channel *chptr = gptr->data;
379
380 channel_members += dlink_list_length(&chptr->members);
381 channel_invites += dlink_list_length(&chptr->invites);
382
383 if (chptr->topic[0])
384 ++topic_count;
385
386 channel_bans += dlink_list_length(&chptr->banlist);
387 channel_ban_memory += dlink_list_length(&chptr->banlist) * sizeof(struct Ban);
388
389 DLINK_FOREACH(dlink, chptr->banlist.head)
390 {
391 actualBan = dlink->data;
392 assert(actualBan->who);
393
394 channel_ban_memory += actualBan->len + 1;
395 channel_ban_memory += strlen(actualBan->who) + 1;
396 }
397
398 channel_except += dlink_list_length(&chptr->exceptlist);
399 channel_except_memory += dlink_list_length(&chptr->exceptlist) * sizeof(struct Ban);
400
401 DLINK_FOREACH(dlink, chptr->exceptlist.head)
402 {
403 actualBan = dlink->data;
404 assert(actualBan->who);
405
406 channel_except_memory += actualBan->len + 1;
407 channel_except_memory += strlen(actualBan->who) + 1;
408 }
409
410 channel_invex += dlink_list_length(&chptr->invexlist);
411 channel_invex_memory += dlink_list_length(&chptr->invexlist) * sizeof(struct Ban);
412
413 DLINK_FOREACH(dlink, chptr->invexlist.head)
414 {
415 actualBan = dlink->data;
416 assert(actualBan->who);
417
418 channel_invex_memory += actualBan->len + 1;
419 channel_invex_memory += strlen(actualBan->who) + 1;
420 }
421 }
422
423 #if 0
424 /* XXX THIS has to be fixed !!!! -db */
425 /* count up all config items */
426 DLINK_FOREACH(dlink, ConfigItemList.head)
427 {
428 aconf = dlink->data;
429 conf_memory += aconf->host ? strlen(aconf->host)+1 : 0;
430 conf_memory += aconf->passwd ? strlen(aconf->passwd)+1 : 0;
431 conf_memory += aconf->name ? strlen(aconf->name)+1 : 0;
432 conf_memory += sizeof(struct AccessItem);
433 }
434 #endif
435 /* count up all classes */
436 class_count = dlink_list_length(class_get_list());
437
438 whowas_count_memory(&wwu, &wwm);
439 watch_count_memory(&watch_list_headers, &watch_list_memory);
440
441 sendto_one(source_p, ":%s %d %s z :WATCH headers %u(%Lu) entries %d(%u)",
442 me.name, RPL_STATSDEBUG, source_p->name, watch_list_headers,
443 watch_list_memory, watch_list_entries,
444 watch_list_entries * sizeof(dlink_node) * 2);
445
446 sendto_one(source_p, ":%s %d %s z :Clients %u(%u)",
447 me.name, RPL_STATSDEBUG, source_p->name, users_counted,
448 (users_counted * sizeof(struct Client)));
449
450 sendto_one(source_p, ":%s %d %s z :User aways %u",
451 me.name, RPL_STATSDEBUG, source_p->name,
452 aways_counted);
453
454 sendto_one(source_p, ":%s %d %s z :Attached confs %u(%Lu)",
455 me.name, RPL_STATSDEBUG, source_p->name,
456 local_client_conf_count,
457 (local_client_conf_count * sizeof(dlink_node)));
458
459 sendto_one(source_p, ":%s %d %s z :Resv channels %u(%u) nicks %u(%u)",
460 me.name, RPL_STATSDEBUG, source_p->name,
461 dlink_list_length(&cresv_items),
462 dlink_list_length(&cresv_items) * sizeof(struct MaskItem),
463 dlink_list_length(&nresv_items),
464 dlink_list_length(&nresv_items) * sizeof(struct MaskItem));
465
466 sendto_one(source_p, ":%s %d %s z :Classes %u(%Lu)",
467 me.name, RPL_STATSDEBUG, source_p->name,
468 class_count, (class_count * sizeof(struct ClassItem)));
469
470 sendto_one(source_p, ":%s %d %s z :Channels %u(%Lu) Topics %u(%u)",
471 me.name, RPL_STATSDEBUG, source_p->name,
472 dlink_list_length(&global_channel_list),
473 channel_memory, topic_count, topic_count *
474 (TOPICLEN + 1 + USERHOST_REPLYLEN));
475
476 sendto_one(source_p, ":%s %d %s z :Bans %u(%Lu)",
477 me.name, RPL_STATSDEBUG, source_p->name,
478 channel_bans, channel_ban_memory);
479
480 sendto_one(source_p, ":%s %d %s z :Exceptions %u(%Lu)",
481 me.name, RPL_STATSDEBUG, source_p->name,
482 channel_except, channel_except_memory);
483
484 sendto_one(source_p, ":%s %d %s z :Invex %u(%Lu)",
485 me.name, RPL_STATSDEBUG, source_p->name,
486 channel_invex, channel_invex_memory);
487
488 sendto_one(source_p, ":%s %d %s z :Channel members %u(%Lu) invites %u(%Lu)",
489 me.name, RPL_STATSDEBUG, source_p->name, channel_members,
490 (channel_members * sizeof(struct Membership)),
491 channel_invites, channel_invites *
492 sizeof(dlink_node) * 2);
493
494 total_channel_memory = channel_memory + channel_ban_memory +
495 channel_members * sizeof(struct Membership) +
496 (channel_invites * sizeof(dlink_node)*2);
497
498 sendto_one(source_p, ":%s %d %s z :Whowas users %u(%Lu)",
499 me.name, RPL_STATSDEBUG, source_p->name,
500 wwu, (wwu * sizeof(struct Client)));
501
502 sendto_one(source_p, ":%s %d %s z :Whowas array %u(%Lu)",
503 me.name, RPL_STATSDEBUG, source_p->name,
504 NICKNAMEHISTORYLENGTH, wwm);
505
506 totww = wwu * sizeof(struct Client) + wwm;
507
508 motd_memory_count(source_p);
509 count_ip_hash(&number_ips_stored,&mem_ips_stored);
510 sendto_one(source_p, ":%s %d %s z :iphash %u(%Lu)",
511 me.name, RPL_STATSDEBUG, source_p->name,
512 number_ips_stored, mem_ips_stored);
513
514 total_memory = totww + total_channel_memory + conf_memory + class_count *
515 sizeof(struct ClassItem);
516 sendto_one(source_p, ":%s %d %s z :Total: whowas %Lu channel %Lu conf %Lu",
517 me.name, RPL_STATSDEBUG, source_p->name, totww,
518 total_channel_memory, conf_memory);
519
520 local_client_memory_used = local_client_count*(sizeof(struct Client) + sizeof(struct Connection));
521 total_memory += local_client_memory_used;
522 sendto_one(source_p, ":%s %d %s z :Local client Memory in use: %u(%Lu)",
523 me.name, RPL_STATSDEBUG, source_p->name, local_client_count,
524 local_client_memory_used);
525
526 remote_client_memory_used = remote_client_count * sizeof(struct Client);
527 total_memory += remote_client_memory_used;
528 sendto_one(source_p, ":%s %d %s z :Remote client Memory in use: %u(%Lu)",
529 me.name, RPL_STATSDEBUG, source_p->name, remote_client_count,
530 remote_client_memory_used);
531
532 sendto_one(source_p,
533 ":%s %d %s z :TOTAL: %Lu",
534 me.name, RPL_STATSDEBUG, source_p->name,
535 total_memory);
536 }
537
538 static void
539 stats_dns_servers(struct Client *source_p)
540 {
541 report_dns_servers(source_p);
542 }
543
544 static void
545 stats_connect(struct Client *source_p, int parc, char *parv[])
546 {
547 report_confitem_types(source_p, CONF_SERVER);
548 }
549
550 /* stats_deny()
551 *
552 * input - client to report to
553 * output - none
554 * side effects - client is given dline list.
555 */
556 static void
557 stats_deny(struct Client *source_p, int parc, char *parv[])
558 {
559 struct MaskItem *conf;
560 dlink_node *ptr = NULL;
561 unsigned int i = 0;
562
563
564 for (i = 0; i < ATABLE_SIZE; ++i)
565 {
566 DLINK_FOREACH(ptr, atable[i].head)
567 {
568 struct AddressRec *arec = ptr->data;
569
570 if (arec->type != CONF_DLINE)
571 continue;
572
573 conf = arec->conf;
574
575 /* dont report a tdline as a dline */
576 if (conf->until)
577 continue;
578
579 sendto_one(source_p, form_str(RPL_STATSDLINE),
580 from, to, 'D', conf->host, conf->reason);
581 }
582 }
583 }
584
585 /* stats_tdeny()
586 *
587 * input - client to report to
588 * output - none
589 * side effects - client is given dline list.
590 */
591 static void
592 stats_tdeny(struct Client *source_p, int parc, char *parv[])
593 {
594 struct MaskItem *conf = NULL;
595 dlink_node *ptr = NULL;
596 unsigned int i = 0;
597
598
599 for (i = 0; i < ATABLE_SIZE; ++i)
600 {
601 DLINK_FOREACH(ptr, atable[i].head)
602 {
603 struct AddressRec *arec = ptr->data;
604
605 if (arec->type != CONF_DLINE)
606 continue;
607
608 conf = arec->conf;
609
610 /* dont report a permanent dline as a tdline */
611 if (!conf->until)
612 continue;
613
614 sendto_one(source_p, form_str(RPL_STATSDLINE),
615 from, to, 'd', conf->host, conf->reason);
616 }
617 }
618 }
619
620 /* stats_exempt()
621 *
622 * input - client to report to
623 * output - none
624 * side effects - client is given list of exempt blocks
625 */
626 static void
627 stats_exempt(struct Client *source_p, int parc, char *parv[])
628 {
629 struct MaskItem *conf;
630 dlink_node *ptr = NULL;
631 unsigned int i = 0;
632
633 if (ConfigFileEntry.stats_e_disabled)
634 {
635 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
636 from, to);
637 return;
638 }
639
640
641 for (i = 0; i < ATABLE_SIZE; ++i)
642 {
643 DLINK_FOREACH(ptr, atable[i].head)
644 {
645 struct AddressRec *arec = ptr->data;
646
647 if (arec->type != CONF_EXEMPT)
648 continue;
649
650 conf = arec->conf;
651
652 sendto_one(source_p, form_str(RPL_STATSDLINE), from, to, 'e',
653 conf->host, "");
654 }
655 }
656 }
657
658 /* stats_pending_glines()
659 *
660 * input - client pointer
661 * output - none
662 * side effects - client is shown list of pending glines
663 */
664 static void
665 stats_pending_glines(struct Client *source_p, int parc, char *parv[])
666 {
667 const dlink_node *dn_ptr = NULL;
668 const struct gline_pending *glp_ptr = NULL;
669 char timebuffer[MAX_DATE_STRING] = { '\0' };
670 struct tm *tmptr = NULL;
671
672 if (!ConfigFileEntry.glines)
673 {
674 sendto_one(source_p, ":%s NOTICE %s :This server does not support G-Lines",
675 from, to);
676 return;
677 }
678
679 if (dlink_list_length(&pending_glines[GLINE_PENDING_ADD_TYPE]) > 0)
680 sendto_one(source_p, ":%s NOTICE %s :Pending G-lines",
681 from, to);
682
683 DLINK_FOREACH(dn_ptr, pending_glines[GLINE_PENDING_ADD_TYPE].head)
684 {
685 glp_ptr = dn_ptr->data;
686 tmptr = localtime(&glp_ptr->vote_1.time_request);
687 strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
688
689 sendto_one(source_p,
690 ":%s NOTICE %s :1) %s!%s@%s on %s requested gline at %s for %s@%s [%s]",
691 from, to, glp_ptr->vote_1.oper_nick,
692 glp_ptr->vote_1.oper_user, glp_ptr->vote_1.oper_host,
693 glp_ptr->vote_1.oper_server, timebuffer,
694 glp_ptr->user, glp_ptr->host, glp_ptr->vote_1.reason);
695
696 if (glp_ptr->vote_2.oper_nick[0] != '\0')
697 {
698 tmptr = localtime(&glp_ptr->vote_2.time_request);
699 strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
700 sendto_one(source_p,
701 ":%s NOTICE %s :2) %s!%s@%s on %s requested gline at %s for %s@%s [%s]",
702 from, to, glp_ptr->vote_2.oper_nick,
703 glp_ptr->vote_2.oper_user, glp_ptr->vote_2.oper_host,
704 glp_ptr->vote_2.oper_server, timebuffer,
705 glp_ptr->user, glp_ptr->host, glp_ptr->vote_2.reason);
706 }
707 }
708
709 sendto_one(source_p, ":%s NOTICE %s :End of Pending G-lines",
710 from, to);
711
712 if (dlink_list_length(&pending_glines[GLINE_PENDING_DEL_TYPE]) > 0)
713 sendto_one(source_p, ":%s NOTICE %s :Pending UNG-lines",
714 from, to);
715
716 DLINK_FOREACH(dn_ptr, pending_glines[GLINE_PENDING_DEL_TYPE].head)
717 {
718 glp_ptr = dn_ptr->data;
719 tmptr = localtime(&glp_ptr->vote_1.time_request);
720 strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
721
722 sendto_one(source_p,
723 ":%s NOTICE %s :1) %s!%s@%s on %s requested ungline at %s for %s@%s [%s]",
724 from, to, glp_ptr->vote_1.oper_nick,
725 glp_ptr->vote_1.oper_user, glp_ptr->vote_1.oper_host,
726 glp_ptr->vote_1.oper_server, timebuffer,
727 glp_ptr->user, glp_ptr->host, glp_ptr->vote_1.reason);
728
729 if (glp_ptr->vote_2.oper_nick[0] != '\0')
730 {
731 tmptr = localtime(&glp_ptr->vote_2.time_request);
732 strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
733 sendto_one(source_p,
734 ":%s NOTICE %s :2) %s!%s@%s on %s requested ungline at %s for %s@%s [%s]",
735 from, to, glp_ptr->vote_2.oper_nick,
736 glp_ptr->vote_2.oper_user, glp_ptr->vote_2.oper_host,
737 glp_ptr->vote_2.oper_server, timebuffer,
738 glp_ptr->user, glp_ptr->host, glp_ptr->vote_2.reason);
739
740 }
741 }
742
743 sendto_one(source_p, ":%s NOTICE %s :End of Pending UNG-lines",
744 from, to);
745 }
746
747 /* stats_glines()
748 *
749 * input - client pointer
750 * output - none
751 * side effects - client is shown list of glines
752 */
753 static void
754 stats_glines(struct Client *source_p, int parc, char *parv[])
755 {
756 dlink_node *ptr = NULL;
757 unsigned int i = 0;
758
759 if (!ConfigFileEntry.glines)
760 {
761 sendto_one(source_p, ":%s NOTICE %s :This server does not support G-Lines",
762 from, to);
763 return;
764 }
765
766 for (i = 0; i < ATABLE_SIZE; ++i)
767 {
768 DLINK_FOREACH(ptr, atable[i].head)
769 {
770 const struct AddressRec *arec = ptr->data;
771
772 if (arec->type == CONF_GLINE)
773 {
774 const struct MaskItem *conf = arec->conf;
775
776 sendto_one(source_p, form_str(RPL_STATSKLINE),
777 from, to, 'G',
778 conf->host ? conf->host : "*",
779 conf->user ? conf->user : "*",
780 conf->reason ? conf->reason : CONF_NOREASON);
781 }
782 }
783 }
784 }
785
786 static void
787 stats_hubleaf(struct Client *source_p, int parc, char *parv[])
788 {
789 const dlink_node *ptr = NULL, *dptr = NULL;
790
791 DLINK_FOREACH(ptr, server_items.head)
792 {
793 const struct MaskItem *conf = ptr->data;
794
795 DLINK_FOREACH(dptr, conf->hub_list.head)
796 sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
797 source_p->name, 'H', dptr->data, conf->name, 0, "*");
798 }
799
800 DLINK_FOREACH(ptr, server_items.head)
801 {
802 const struct MaskItem *conf = ptr->data;
803
804 DLINK_FOREACH(dptr, conf->leaf_list.head)
805 sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
806 source_p->name, 'L', dptr->data, conf->name, 0, "*");
807 }
808 }
809
810 /*
811 * show_iline_prefix()
812 *
813 * inputs - pointer to struct Client requesting output
814 * - pointer to struct MaskItem
815 * - name to which iline prefix will be prefixed to
816 * output - pointer to static string with prefixes listed in ascii form
817 * side effects - NONE
818 */
819 static const char *
820 show_iline_prefix(const struct Client *sptr, const struct MaskItem *conf)
821 {
822 static char prefix_of_host[USERLEN + 15];
823 char *prefix_ptr = prefix_of_host;
824
825 if (IsConfWebIRC(conf))
826 *prefix_ptr++ = '<';
827 if (IsNoTilde(conf))
828 *prefix_ptr++ = '-';
829 if (IsLimitIp(conf))
830 *prefix_ptr++ = '!';
831 if (IsNeedIdentd(conf))
832 *prefix_ptr++ = '+';
833 if (!IsNeedPassword(conf))
834 *prefix_ptr++ = '&';
835 if (IsConfExemptResv(conf))
836 *prefix_ptr++ = '$';
837 if (IsNoMatchIp(conf))
838 *prefix_ptr++ = '%';
839 if (IsConfDoSpoofIp(conf))
840 *prefix_ptr++ = '=';
841 if (MyOper(sptr) && IsConfExemptKline(conf))
842 *prefix_ptr++ = '^';
843 if (MyOper(sptr) && IsConfExemptGline(conf))
844 *prefix_ptr++ = '_';
845 if (MyOper(sptr) && IsConfExemptLimits(conf))
846 *prefix_ptr++ = '>';
847 if (IsConfCanFlood(conf))
848 *prefix_ptr++ = '|';
849
850 strlcpy(prefix_ptr, conf->user, USERLEN+1);
851
852 return prefix_of_host;
853 }
854
855 static void
856 report_auth(struct Client *client_p, int parc, char *parv[])
857 {
858 struct MaskItem *conf = NULL;
859 dlink_node *ptr = NULL;
860 unsigned int i;
861
862
863 for (i = 0; i < ATABLE_SIZE; ++i)
864 {
865 DLINK_FOREACH(ptr, atable[i].head)
866 {
867 struct AddressRec *arec = ptr->data;
868
869 if (arec->type != CONF_CLIENT)
870 continue;
871
872 conf = arec->conf;
873
874 if (!MyOper(client_p) && IsConfDoSpoofIp(conf))
875 continue;
876
877 /* We are doing a partial list, based on what matches the u@h of the
878 * sender, so prepare the strings for comparing --fl_
879 */
880 if (ConfigFileEntry.hide_spoof_ips)
881 sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
882 client_p->name, 'I',
883 conf->name == NULL ? "*" : conf->name,
884 show_iline_prefix(client_p, conf),
885 IsConfDoSpoofIp(conf) ? "255.255.255.255" :
886 conf->host, conf->port,
887 conf->class ? conf->class->name : "<default>");
888
889 else
890 sendto_one(client_p, form_str(RPL_STATSILINE), me.name,
891 client_p->name, 'I',
892 conf->name == NULL ? "*" : conf->name,
893 show_iline_prefix(client_p, conf),
894 conf->host, conf->port,
895 conf->class ? conf->class->name : "<default>");
896 }
897 }
898 }
899
900 static void
901 stats_auth(struct Client *source_p, int parc, char *parv[])
902 {
903 /* Oper only, if unopered, return ERR_NOPRIVILEGES */
904 if ((ConfigFileEntry.stats_i_oper_only == 2) && !HasUMode(source_p, UMODE_OPER))
905 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
906 from, to);
907
908 /* If unopered, Only return matching auth blocks */
909 else if ((ConfigFileEntry.stats_i_oper_only == 1) && !HasUMode(source_p, UMODE_OPER))
910 {
911 struct MaskItem *conf;
912
913 if (MyConnect(source_p))
914 conf = find_conf_by_address(source_p->host,
915 &source_p->localClient->ip,
916 CONF_CLIENT,
917 source_p->localClient->aftype,
918 source_p->username,
919 source_p->localClient->passwd, 1);
920 else
921 conf = find_conf_by_address(source_p->host, NULL, CONF_CLIENT,
922 0, source_p->username, NULL, 1);
923
924 if (conf == NULL)
925 return;
926
927 sendto_one(source_p, form_str(RPL_STATSILINE), from,
928 to, 'I',
929 "*", show_iline_prefix(source_p, conf),
930 conf->host, conf->port,
931 conf->class ? conf->class->name : "<default>");
932 }
933 /* They are opered, or allowed to see all auth blocks */
934 else
935 report_auth(source_p, 0, NULL);
936 }
937
938 /* report_Klines()
939 * Inputs: Client to report to,
940 * type(==0 for perm, !=0 for temporary)
941 * mask
942 * Output: None
943 * Side effects: Reports configured K(or k)-lines to client_p.
944 */
945 static void
946 report_Klines(struct Client *client_p, int tkline)
947 {
948 struct MaskItem *conf = NULL;
949 unsigned int i = 0;
950 char c = '\0';
951 dlink_node *ptr = NULL;
952
953 if (tkline)
954 c = 'k';
955 else
956 c = 'K';
957
958 for (i = 0; i < ATABLE_SIZE; ++i)
959 {
960 DLINK_FOREACH(ptr, atable[i].head)
961 {
962 struct AddressRec *arec = ptr->data;
963
964 if (arec->type != CONF_KLINE)
965 continue;
966
967 conf = arec->conf;
968
969 if ((!tkline && conf->until) ||
970 (tkline && !conf->until))
971 continue;
972
973 if (HasUMode(client_p, UMODE_OPER))
974 sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
975 client_p->name, c, conf->host, conf->user,
976 conf->reason);
977 else
978 sendto_one(client_p, form_str(RPL_STATSKLINE), me.name,
979 client_p->name, c, conf->host, conf->user,
980 conf->reason);
981 }
982 }
983 }
984
985 static void
986 stats_tklines(struct Client *source_p, int parc, char *parv[])
987 {
988 /* Oper only, if unopered, return ERR_NOPRIVILEGES */
989 if ((ConfigFileEntry.stats_k_oper_only == 2) && !HasUMode(source_p, UMODE_OPER))
990 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
991 from, to);
992
993 /* If unopered, Only return matching klines */
994 else if ((ConfigFileEntry.stats_k_oper_only == 1) && !HasUMode(source_p, UMODE_OPER))
995 {
996 struct MaskItem *conf = NULL;
997
998 if (MyConnect(source_p))
999 conf = find_conf_by_address(source_p->host,
1000 &source_p->localClient->ip,
1001 CONF_KLINE,
1002 source_p->localClient->aftype,
1003 source_p->username, NULL, 1);
1004 else
1005 conf = find_conf_by_address(source_p->host, NULL, CONF_KLINE,
1006 0, source_p->username, NULL, 1);
1007
1008 if (!conf)
1009 return;
1010
1011 /* dont report a permanent kline as a tkline */
1012 if (!conf->until)
1013 return;
1014
1015 sendto_one(source_p, form_str(RPL_STATSKLINE), from,
1016 to, 'k', conf->host, conf->user, conf->reason);
1017 }
1018 /* Theyre opered, or allowed to see all klines */
1019 else {
1020 report_Klines(source_p, 1);
1021 }
1022 }
1023
1024 static void
1025 stats_klines(struct Client *source_p, int parc, char *parv[])
1026 {
1027 /* Oper only, if unopered, return ERR_NOPRIVILEGES */
1028 if ((ConfigFileEntry.stats_k_oper_only == 2) && !HasUMode(source_p, UMODE_OPER))
1029 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1030 from, to);
1031
1032 /* If unopered, Only return matching klines */
1033 else if ((ConfigFileEntry.stats_k_oper_only == 1) && !HasUMode(source_p, UMODE_OPER))
1034 {
1035 struct MaskItem *conf = NULL;
1036
1037 /* search for a kline */
1038 if (MyConnect(source_p))
1039 conf = find_conf_by_address(source_p->host,
1040 &source_p->localClient->ip,
1041 CONF_KLINE,
1042 source_p->localClient->aftype,
1043 source_p->username, NULL, 0);
1044 else
1045 conf = find_conf_by_address(source_p->host, NULL, CONF_KLINE,
1046 0, source_p->username, NULL, 0);
1047
1048 if (!conf)
1049 return;
1050
1051 /* dont report a tkline as a kline */
1052 if (conf->until)
1053 return;
1054
1055 sendto_one(source_p, form_str(RPL_STATSKLINE), from,
1056 to, 'K', conf->host, conf->user, conf->reason);
1057 }
1058 /* Theyre opered, or allowed to see all klines */
1059 else
1060 report_Klines(source_p, 0);
1061 }
1062
1063 static void
1064 stats_messages(struct Client *source_p, int parc, char *parv[])
1065 {
1066 report_messages(source_p);
1067 }
1068
1069 static void
1070 stats_oper(struct Client *source_p, int parc, char *parv[])
1071 {
1072 if (!HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.stats_o_oper_only)
1073 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1074 from, to);
1075 else
1076 report_confitem_types(source_p, CONF_OPER);
1077 }
1078
1079 /* stats_operedup()
1080 *
1081 * input - client pointer
1082 * output - none
1083 * side effects - client is shown a list of active opers
1084 */
1085 static void
1086 stats_operedup(struct Client *source_p, int parc, char *parv[])
1087 {
1088 dlink_node *ptr;
1089
1090 DLINK_FOREACH(ptr, oper_list.head)
1091 {
1092 const struct Client *target_p = ptr->data;
1093
1094 if (HasUMode(target_p, UMODE_HIDDEN) && !HasUMode(source_p, UMODE_OPER))
1095 continue;
1096
1097 if (MyClient(source_p) && HasUMode(source_p, UMODE_OPER))
1098 sendto_one(source_p, ":%s %d %s p :[%c][%s] %s (%s@%s) Idle: %u",
1099 from, RPL_STATSDEBUG, to,
1100 HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O',
1101 oper_privs_as_string(target_p->localClient->operflags),
1102 target_p->name, target_p->username, target_p->host,
1103 idle_time_get(source_p, target_p));
1104 else
1105 sendto_one(source_p, ":%s %d %s p :[%c] %s (%s@%s) Idle: %u",
1106 from, RPL_STATSDEBUG, to,
1107 HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O',
1108 target_p->name, target_p->username, target_p->host,
1109 idle_time_get(source_p, target_p));
1110 }
1111
1112 sendto_one(source_p, ":%s %d %s p :%u OPER(s)",
1113 from, RPL_STATSDEBUG, to, dlink_list_length(&oper_list));
1114 }
1115
1116 static void
1117 stats_ports(struct Client *source_p, int parc, char *parv[])
1118 {
1119 if (!HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.stats_P_oper_only)
1120 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1121 from, to);
1122 else
1123 show_ports(source_p);
1124 }
1125
1126 static void
1127 stats_resv(struct Client *source_p, int parc, char *parv[])
1128 {
1129 report_resv(source_p);
1130 }
1131
1132 static void
1133 stats_service(struct Client *source_p, int parc, char *parv[])
1134 {
1135 report_confitem_types(source_p, CONF_SERVICE);
1136 }
1137
1138 static void
1139 stats_tstats(struct Client *source_p, int parc, char *parv[])
1140 {
1141 const struct Client *target_p = NULL;
1142 const dlink_node *ptr = NULL;
1143 struct ServerStatistics tmp;
1144 struct ServerStatistics *sp = &tmp;
1145
1146 memcpy(sp, &ServerStats, sizeof(struct ServerStatistics));
1147
1148 /*
1149 * must use the += operator. is_sv is not the number of currently
1150 * active server connections. Note the incrementation in
1151 * s_bsd.c:close_connection.
1152 */
1153 sp->is_sv += dlink_list_length(&serv_list);
1154
1155 DLINK_FOREACH(ptr, serv_list.head)
1156 {
1157 target_p = ptr->data;
1158
1159 sp->is_sbs += target_p->localClient->send.bytes;
1160 sp->is_sbr += target_p->localClient->recv.bytes;
1161 sp->is_sti += CurrentTime - target_p->localClient->firsttime;
1162 }
1163
1164 sp->is_cl += dlink_list_length(&local_client_list);
1165
1166 DLINK_FOREACH(ptr, local_client_list.head)
1167 {
1168 target_p = ptr->data;
1169
1170 sp->is_cbs += target_p->localClient->send.bytes;
1171 sp->is_cbr += target_p->localClient->recv.bytes;
1172 sp->is_cti += CurrentTime - target_p->localClient->firsttime;
1173 }
1174
1175 sp->is_ni += dlink_list_length(&unknown_list);
1176
1177 sendto_one(source_p, ":%s %d %s T :accepts %u refused %u",
1178 me.name, RPL_STATSDEBUG, source_p->name, sp->is_ac, sp->is_ref);
1179 sendto_one(source_p, ":%s %d %s T :unknown commands %u prefixes %u",
1180 me.name, RPL_STATSDEBUG, source_p->name, sp->is_unco, sp->is_unpf);
1181 sendto_one(source_p, ":%s %d %s T :nick collisions %u unknown closes %u",
1182 me.name, RPL_STATSDEBUG, source_p->name, sp->is_kill, sp->is_ni);
1183 sendto_one(source_p, ":%s %d %s T :wrong direction %u empty %u",
1184 me.name, RPL_STATSDEBUG, source_p->name, sp->is_wrdi, sp->is_empt);
1185 sendto_one(source_p, ":%s %d %s T :numerics seen %u",
1186 me.name, RPL_STATSDEBUG, source_p->name, sp->is_num);
1187 sendto_one(source_p, ":%s %d %s T :auth successes %u fails %u",
1188 me.name, RPL_STATSDEBUG, source_p->name, sp->is_asuc, sp->is_abad);
1189 sendto_one(source_p, ":%s %d %s T :Client Server",
1190 me.name, RPL_STATSDEBUG, source_p->name);
1191
1192 sendto_one(source_p, ":%s %d %s T :connected %u %u",
1193 me.name, RPL_STATSDEBUG, source_p->name,
1194 sp->is_cl,
1195 sp->is_sv);
1196 sendto_one(source_p, ":%s %d %s T :bytes sent %Lu %Lu",
1197 me.name, RPL_STATSDEBUG, source_p->name,
1198 sp->is_cbs, sp->is_sbs);
1199 sendto_one(source_p, ":%s %d %s T :bytes recv %Lu %Lu",
1200 me.name, RPL_STATSDEBUG, source_p->name,
1201 sp->is_cbr, sp->is_sbr);
1202 sendto_one(source_p, ":%s %d %s T :time connected %Lu %Lu",
1203 me.name, RPL_STATSDEBUG, source_p->name,
1204 sp->is_cti, sp->is_sti);
1205 }
1206
1207 static void
1208 stats_uptime(struct Client *source_p, int parc, char *parv[])
1209 {
1210 if (!HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.stats_u_oper_only)
1211 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1212 from, to);
1213 else
1214 {
1215 time_t now = CurrentTime - me.localClient->since;
1216
1217 sendto_one(source_p, form_str(RPL_STATSUPTIME), from, to,
1218 now / 86400, (now / 3600) % 24, (now / 60) % 60, now % 60);
1219
1220 if (!ConfigServerHide.disable_remote_commands || HasUMode(source_p, UMODE_OPER))
1221 sendto_one(source_p, form_str(RPL_STATSCONN), from, to,
1222 Count.max_loc_con, Count.max_loc_cli, Count.totalrestartcount);
1223 }
1224 }
1225
1226 static void
1227 stats_engine(struct Client *source_p, int parc, char *parv[])
1228 {
1229 sendto_one(source_p, form_str(RPL_STATSENGINE), from, to, engine_name());
1230 }
1231
1232 static void
1233 stats_shared(struct Client *source_p, int parc, char *parv[])
1234 {
1235 report_confitem_types(source_p, CONF_ULINE);
1236 }
1237
1238 /* stats_servers()
1239 *
1240 * input - client pointer
1241 * output - none
1242 * side effects - client is shown lists of who connected servers
1243 */
1244 static void
1245 stats_servers(struct Client *source_p, int parc, char *parv[])
1246 {
1247 dlink_node *ptr = NULL;
1248
1249 DLINK_FOREACH(ptr, serv_list.head)
1250 {
1251 const struct Client *target_p = ptr->data;
1252
1253 sendto_one(source_p, ":%s %d %s v :%s (%s!%s@%s) Idle: %Tu",
1254 from, RPL_STATSDEBUG, to, target_p->name,
1255 (target_p->serv->by[0] ? target_p->serv->by : "Remote."),
1256 "*", "*", (CurrentTime - target_p->localClient->lasttime));
1257 }
1258
1259 sendto_one(source_p, ":%s %d %s v :%u Server(s)",
1260 from, RPL_STATSDEBUG, to, dlink_list_length(&serv_list));
1261 }
1262
1263 static void
1264 stats_gecos(struct Client *source_p, int parc, char *parv[])
1265 {
1266 report_confitem_types(source_p, CONF_XLINE);
1267 }
1268
1269 static void
1270 stats_class(struct Client *source_p, int parc, char *parv[])
1271 {
1272 const dlink_node *ptr = NULL;
1273
1274 DLINK_FOREACH(ptr, class_get_list()->head)
1275 {
1276 const struct ClassItem *class = ptr->data;
1277
1278 sendto_one(source_p, form_str(RPL_STATSYLINE),
1279 me.name, source_p->name, 'Y',
1280 class->name, class->ping_freq,
1281 class->con_freq,
1282 class->max_total, class->max_sendq,
1283 class->max_recvq,
1284 class->ref_count,
1285 class->number_per_cidr, class->cidr_bitlen_ipv4,
1286 class->number_per_cidr, class->cidr_bitlen_ipv6,
1287 class->active ? "active" : "disabled");
1288 }
1289 }
1290
1291 static void
1292 stats_servlinks(struct Client *source_p, int parc, char *parv[])
1293 {
1294 uint64_t sendB = 0, recvB = 0;
1295 time_t uptime = 0;
1296 dlink_node *ptr = NULL;
1297
1298 if (ConfigServerHide.flatten_links && !HasUMode(source_p, UMODE_OPER))
1299 {
1300 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1301 from, to);
1302 return;
1303 }
1304
1305 DLINK_FOREACH(ptr, serv_list.head)
1306 {
1307 struct Client *target_p = ptr->data;
1308
1309 if (HasFlag(target_p, FLAGS_SERVICE) && ConfigServerHide.hide_services)
1310 if (!HasUMode(source_p, UMODE_OPER))
1311 continue;
1312
1313 sendB += target_p->localClient->send.bytes;
1314 recvB += target_p->localClient->recv.bytes;
1315
1316 /* ":%s 211 %s %s %u %u %llu %u %llu :%u %u %s" */
1317 sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1318 from, to,
1319 get_client_name(target_p, HasUMode(source_p, UMODE_ADMIN) ? SHOW_IP : MASK_IP),
1320 MsgQLength(&target_p->localClient->sendQ),
1321 target_p->localClient->send.messages,
1322 target_p->localClient->send.bytes >> 10,
1323 target_p->localClient->recv.messages,
1324 target_p->localClient->recv.bytes >> 10,
1325 (unsigned)(CurrentTime - target_p->localClient->firsttime),
1326 (CurrentTime > target_p->localClient->since) ? (unsigned)(CurrentTime - target_p->localClient->since): 0,
1327 HasUMode(source_p, UMODE_OPER) ? show_capabilities(target_p) : "TS");
1328 }
1329
1330 sendB >>= 10;
1331 recvB >>= 10;
1332
1333 sendto_one(source_p, ":%s %d %s ? :%u total server(s)",
1334 from, RPL_STATSDEBUG, to, dlink_list_length(&serv_list));
1335 sendto_one(source_p, ":%s %d %s ? :Sent total : %7.2f %s",
1336 from, RPL_STATSDEBUG, to,
1337 _GMKv(sendB), _GMKs(sendB));
1338 sendto_one(source_p, ":%s %d %s ? :Recv total : %7.2f %s",
1339 from, RPL_STATSDEBUG, to,
1340 _GMKv(recvB), _GMKs(recvB));
1341
1342 uptime = (CurrentTime - me.localClient->since);
1343
1344 sendto_one(source_p, ":%s %d %s ? :Server send: %7.2f %s (%4.1f K/s)",
1345 from, RPL_STATSDEBUG, to,
1346 _GMKv((me.localClient->send.bytes>>10)),
1347 _GMKs((me.localClient->send.bytes>>10)),
1348 (float)((float)((me.localClient->send.bytes) >> 10) /
1349 (float)uptime));
1350 sendto_one(source_p, ":%s %d %s ? :Server recv: %7.2f %s (%4.1f K/s)",
1351 from, RPL_STATSDEBUG, to,
1352 _GMKv((me.localClient->recv.bytes>>10)),
1353 _GMKs((me.localClient->recv.bytes>>10)),
1354 (float)((float)((me.localClient->recv.bytes) >> 10) /
1355 (float)uptime));
1356 }
1357
1358 /* parse_stats_args()
1359 *
1360 * inputs - arg count
1361 * - args
1362 * - doall flag
1363 * - wild card or not
1364 * output - pointer to name to use
1365 * side effects -
1366 * common parse routine for m_stats args
1367 *
1368 */
1369 static char *
1370 parse_stats_args(int parc, char *parv[], int *doall, int *wilds)
1371 {
1372 char *name;
1373
1374 if (parc > 2)
1375 {
1376 name = parv[2];
1377
1378 if (!irccmp(name, from))
1379 *doall = 2;
1380 else if (!match(name, from))
1381 *doall = 1;
1382
1383 *wilds = has_wildcards(name);
1384
1385 return name;
1386 }
1387
1388 return NULL;
1389 }
1390
1391 static void
1392 stats_L_list(struct Client *source_p,char *name, int doall, int wilds,
1393 dlink_list *list,char statchar)
1394 {
1395 dlink_node *ptr;
1396 struct Client *target_p;
1397
1398 /*
1399 * send info about connections which match, or all if the
1400 * mask matches from. Only restrictions are on those who
1401 * are invisible not being visible to 'foreigners' who use
1402 * a wild card based search to list it.
1403 */
1404 DLINK_FOREACH(ptr, list->head)
1405 {
1406 target_p = ptr->data;
1407
1408 if (HasUMode(target_p, UMODE_INVISIBLE) && (doall || wilds) &&
1409 !(MyConnect(source_p) && HasUMode(source_p, UMODE_OPER)) &&
1410 !HasUMode(target_p, UMODE_OPER) && (target_p != source_p))
1411 continue;
1412 if (!doall && wilds && match(name, target_p->name))
1413 continue;
1414 if (!(doall || wilds) && irccmp(name, target_p->name))
1415 continue;
1416
1417 /* This basically shows ips for our opers if its not a server/admin, or
1418 * its one of our admins. */
1419 if(MyClient(source_p) && HasUMode(source_p, UMODE_OPER) &&
1420 (HasUMode(source_p, UMODE_ADMIN) ||
1421 (!IsServer(target_p) && !HasUMode(target_p, UMODE_ADMIN) &&
1422 !IsHandshake(target_p) && !IsConnecting(target_p))))
1423 {
1424 sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1425 from, to,
1426 (IsUpper(statchar)) ?
1427 get_client_name(target_p, SHOW_IP) :
1428 get_client_name(target_p, HIDE_IP),
1429 MsgQLength(&target_p->localClient->sendQ),
1430 target_p->localClient->send.messages,
1431 target_p->localClient->send.bytes>>10,
1432 target_p->localClient->recv.messages,
1433 target_p->localClient->recv.bytes>>10,
1434 (unsigned)(CurrentTime - target_p->localClient->firsttime),
1435 (CurrentTime > target_p->localClient->since) ? (unsigned)(CurrentTime - target_p->localClient->since):0,
1436 IsServer(target_p) ? show_capabilities(target_p) : "-");
1437 }
1438 else
1439 {
1440 /* If its a hidden ip, an admin, or a server, mask the real IP */
1441 if(IsIPSpoof(target_p) || IsServer(target_p) || HasUMode(target_p, UMODE_ADMIN)
1442 || IsHandshake(target_p) || IsConnecting(target_p))
1443 sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1444 from, to,
1445 get_client_name(target_p, MASK_IP),
1446 MsgQLength(&target_p->localClient->sendQ),
1447 target_p->localClient->send.messages,
1448 target_p->localClient->send.bytes>>10,
1449 target_p->localClient->recv.messages,
1450 target_p->localClient->recv.bytes>>10,
1451 (unsigned)(CurrentTime - target_p->localClient->firsttime),
1452 (CurrentTime > target_p->localClient->since) ? (unsigned)(CurrentTime - target_p->localClient->since):0,
1453 IsServer(target_p) ? show_capabilities(target_p) : "-");
1454 else /* show the real IP */
1455 sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1456 from, to,
1457 (IsUpper(statchar)) ?
1458 get_client_name(target_p, SHOW_IP) :
1459 get_client_name(target_p, HIDE_IP),
1460 MsgQLength(&target_p->localClient->sendQ),
1461 target_p->localClient->send.messages,
1462 target_p->localClient->send.bytes>>10,
1463 target_p->localClient->recv.messages,
1464 target_p->localClient->recv.bytes>>10,
1465 (unsigned)(CurrentTime - target_p->localClient->firsttime),
1466 (CurrentTime > target_p->localClient->since) ? (unsigned)(CurrentTime - target_p->localClient->since):0,
1467 IsServer(target_p) ? show_capabilities(target_p) : "-");
1468 }
1469 }
1470 }
1471
1472 /*
1473 * stats_L
1474 *
1475 * inputs - pointer to client to report to
1476 * - doall flag
1477 * - wild card or not
1478 * output - NONE
1479 * side effects -
1480 */
1481 static void
1482 stats_L(struct Client *source_p,char *name,int doall,
1483 int wilds,char statchar)
1484 {
1485 stats_L_list(source_p, name, doall, wilds, &unknown_list, statchar);
1486 stats_L_list(source_p, name, doall, wilds, &local_client_list, statchar);
1487 stats_L_list(source_p, name, doall, wilds, &serv_list, statchar);
1488 }
1489
1490 static void
1491 stats_ltrace(struct Client *source_p, int parc, char *parv[])
1492 {
1493 int doall = 0;
1494 int wilds = 0;
1495 char *name = NULL;
1496 char statchar;
1497
1498 if ((name = parse_stats_args(parc, parv, &doall, &wilds)) != NULL)
1499 {
1500 statchar = parv[1][0];
1501
1502 stats_L(source_p, name, doall, wilds, statchar);
1503 }
1504 else
1505 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1506 from, to, "STATS");
1507 }
1508
1509 static const struct StatsStruct
1510 {
1511 const unsigned char letter;
1512 void (*handler)();
1513 const unsigned int need_oper;
1514 const unsigned int need_admin;
1515 } stats_cmd_table[] = {
1516 /* letter function need_oper need_admin */
1517 { 'a', stats_dns_servers, 1, 1 },
1518 { 'A', stats_dns_servers, 1, 1 },
1519 { 'c', stats_connect, 1, 0 },
1520 { 'C', stats_connect, 1, 0 },
1521 { 'd', stats_tdeny, 1, 0 },
1522 { 'D', stats_deny, 1, 0 },
1523 { 'e', stats_exempt, 1, 0 },
1524 { 'E', stats_engine, 1, 1 },
1525 { 'g', stats_pending_glines, 1, 0 },
1526 { 'G', stats_glines, 1, 0 },
1527 { 'h', stats_hooks, 1, 1 },
1528 { 'H', stats_hubleaf, 1, 0 },
1529 { 'i', stats_auth, 0, 0 },
1530 { 'I', stats_auth, 0, 0 },
1531 { 'k', stats_tklines, 0, 0 },
1532 { 'K', stats_klines, 0, 0 },
1533 { 'l', stats_ltrace, 1, 0 },
1534 { 'L', stats_ltrace, 1, 0 },
1535 { 'm', stats_messages, 0, 0 },
1536 { 'M', stats_messages, 0, 0 },
1537 { 'o', stats_oper, 0, 0 },
1538 { 'O', stats_oper, 0, 0 },
1539 { 'p', stats_operedup, 0, 0 },
1540 { 'P', stats_ports, 0, 0 },
1541 { 'q', stats_resv, 1, 0 },
1542 { 'Q', stats_resv, 1, 0 },
1543 { 'r', stats_usage, 1, 0 },
1544 { 'R', stats_usage, 1, 0 },
1545 { 's', stats_service, 1, 0 },
1546 { 'S', stats_service, 1, 0 },
1547 { 't', stats_tstats, 1, 0 },
1548 { 'T', motd_report, 1, 0 },
1549 { 'u', stats_uptime, 0, 0 },
1550 { 'U', stats_shared, 1, 0 },
1551 { 'v', stats_servers, 1, 0 },
1552 { 'x', stats_gecos, 1, 0 },
1553 { 'X', stats_gecos, 1, 0 },
1554 { 'y', stats_class, 1, 0 },
1555 { 'Y', stats_class, 1, 0 },
1556 { 'z', stats_memory, 1, 0 },
1557 { '?', stats_servlinks, 0, 0 },
1558 { '\0', NULL, 0, 0 }
1559 };
1560
1561 static int
1562 do_stats(struct Client *source_p, int parc, char *parv[])
1563 {
1564 const struct StatsStruct *tab = stats_cmd_table;
1565 const char statchar = *parv[1];
1566
1567 if (statchar == '\0')
1568 {
1569 sendto_one(source_p, form_str(RPL_ENDOFSTATS),
1570 from, to, '*');
1571 return 0;
1572 }
1573
1574 for (; tab->handler; ++tab)
1575 {
1576 if (tab->letter == statchar)
1577 {
1578 /* The stats table says what privs are needed, so check --fl_ */
1579 if ((tab->need_admin && !HasUMode(source_p, UMODE_ADMIN)) ||
1580 (tab->need_oper && !HasUMode(source_p, UMODE_OPER)))
1581 {
1582 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1583 from, to);
1584 break;
1585 }
1586
1587 sendto_realops_flags(UMODE_SPY, L_ALL, SEND_NOTICE,
1588 "STATS %c requested by %s (%s@%s) [%s]",
1589 statchar, source_p->name, source_p->username,
1590 source_p->host, source_p->servptr->name);
1591 tab->handler(source_p, parc, parv);
1592 break;
1593 }
1594 }
1595
1596 sendto_one(source_p, form_str(RPL_ENDOFSTATS),
1597 from, to, statchar);
1598 return 0;
1599 }
1600
1601 /*
1602 * m_stats()
1603 * parv[0] = sender prefix
1604 * parv[1] = stat letter/command
1605 * parv[2] = (if present) server/mask in stats L
1606 *
1607 * This will search the tables for the appropriate stats letter/command,
1608 * if found execute it.
1609 */
1610 static int
1611 m_stats(struct Client *client_p, struct Client *source_p,
1612 int parc, char *parv[])
1613 {
1614 static time_t last_used = 0;
1615
1616 if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
1617 {
1618 from = me.id;
1619 to = source_p->id;
1620 }
1621 else
1622 {
1623 from = me.name;
1624 to = source_p->name;
1625 }
1626
1627 /* Check the user is actually allowed to do /stats, and isnt flooding */
1628 if ((last_used + ConfigFileEntry.pace_wait) > CurrentTime)
1629 {
1630 sendto_one(source_p,form_str(RPL_LOAD2HI),
1631 from, to);
1632 return 0;
1633 }
1634
1635 last_used = CurrentTime;
1636
1637 /* Is the stats meant for us? */
1638 if (!ConfigServerHide.disable_remote_commands)
1639 if (hunt_server(client_p, source_p, ":%s STATS %s :%s", 2,
1640 parc, parv) != HUNTED_ISME)
1641 return 0;
1642
1643 return do_stats(source_p, parc, parv);
1644 }
1645
1646 /*
1647 * mo_stats()
1648 * parv[0] = sender prefix
1649 * parv[1] = stat letter/command
1650 * parv[2] = (if present) server/mask in stats L, or target
1651 *
1652 * This will search the tables for the appropriate stats letter,
1653 * if found execute it.
1654 */
1655 static int
1656 mo_stats(struct Client *client_p, struct Client *source_p,
1657 int parc, char *parv[])
1658 {
1659 if (hunt_server(client_p, source_p, ":%s STATS %s :%s", 2,
1660 parc, parv) != HUNTED_ISME)
1661 return 0;
1662
1663 if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
1664 {
1665 from = me.id;
1666 to = source_p->id;
1667 }
1668 else
1669 {
1670 from = me.name;
1671 to = source_p->name;
1672 }
1673
1674 return do_stats(source_p, parc, parv);
1675 }
1676
1677 static struct Message stats_msgtab =
1678 {
1679 "STATS", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
1680 { m_unregistered, m_stats, mo_stats, m_ignore, mo_stats, m_ignore }
1681 };
1682
1683 static void
1684 module_init(void)
1685 {
1686 mod_add_cmd(&stats_msgtab);
1687 }
1688
1689 static void
1690 module_exit(void)
1691 {
1692 mod_del_cmd(&stats_msgtab);
1693 }
1694
1695 struct module module_entry =
1696 {
1697 .node = { NULL, NULL, NULL },
1698 .name = NULL,
1699 .version = "$Revision$",
1700 .handle = NULL,
1701 .modinit = module_init,
1702 .modexit = module_exit,
1703 .flags = 0
1704 };

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28