ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_stats.c
Revision: 1302
Committed: Wed Mar 21 17:48:54 2012 UTC (12 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/m_stats.c
File size: 46236 byte(s)
Log Message:
- remove servlink in preparation for tls links/compression

File Contents

# Content
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 "balloc.h"
28 #include "client.h" /* Client */
29 #include "irc_string.h"
30 #include "ircd.h" /* me */
31 #include "listener.h" /* show_ports */
32 #include "s_gline.h"
33 #include "hostmask.h"
34 #include "numeric.h" /* ERR_xxx */
35 #include "send.h" /* sendto_one */
36 #include "fdlist.h" /* PF and friends */
37 #include "s_bsd.h" /* highest_fd */
38 #include "s_conf.h" /* AccessItem, report_configured_links */
39 #include "s_misc.h" /* serv_info */
40 #include "s_serv.h" /* hunt_server */
41 #include "s_user.h" /* show_opers */
42 #include "event.h" /* events */
43 #include "dbuf.h"
44 #include "hook.h"
45 #include "parse.h"
46 #include "modules.h"
47 #include "resv.h" /* report_resv */
48 #include "whowas.h"
49 #include "watch.h"
50
51
52 static char *parse_stats_args(int, char **, int *, int *);
53 static void stats_L(struct Client *, char *, int, int, char);
54 static void stats_L_list(struct Client *, char *, int, int, dlink_list *, char);
55 static void stats_dns_servers(struct Client *);
56 static void stats_connect(struct Client *);
57 static void stats_deny(struct Client *);
58 static void stats_tdeny(struct Client *);
59 static void stats_exempt(struct Client *);
60 static void stats_events(struct Client *);
61 static void stats_pending_glines(struct Client *);
62 static void stats_glines(struct Client *);
63 static void stats_gdeny(struct Client *);
64 static void stats_hubleaf(struct Client *);
65 static void stats_auth(struct Client *);
66 static void stats_tklines(struct Client *);
67 static void stats_klines(struct Client *);
68 static void stats_messages(struct Client *);
69 static void stats_oper(struct Client *);
70 static void stats_operedup(struct Client *);
71 static void stats_ports(struct Client *);
72 static void stats_resv(struct Client *);
73 static void stats_usage(struct Client *);
74 static void stats_service(struct Client *);
75 static void stats_tstats(struct Client *);
76 static void stats_uptime(struct Client *);
77 static void stats_shared(struct Client *);
78 static void stats_servers(struct Client *);
79 static void stats_gecos(struct Client *);
80 static void stats_class(struct Client *);
81 static void stats_memory(struct Client *);
82 static void stats_servlinks(struct Client *);
83 static void stats_ltrace(struct Client *, int, char **);
84
85 /* This table contains the possible stats items, in order:
86 * /stats name, function to call, operonly? adminonly? /stats letter
87 * case only matters in the stats letter column.. -- fl_ */
88 static const struct StatsStruct
89 {
90 const unsigned char letter;
91 void (*handler)();
92 const unsigned int need_oper;
93 const unsigned int need_admin;
94 } stats_cmd_table[] = {
95 /* letter function need_oper need_admin */
96 { 'a', stats_dns_servers, 1, 1 },
97 { 'A', stats_dns_servers, 1, 1 },
98 { 'c', stats_connect, 1, 0 },
99 { 'C', stats_connect, 1, 0 },
100 { 'd', stats_tdeny, 1, 0 },
101 { 'D', stats_deny, 1, 0 },
102 { 'e', stats_exempt, 1, 0 },
103 { 'E', stats_events, 1, 1 },
104 { 'f', fd_dump, 1, 1 },
105 { 'F', fd_dump, 1, 1 },
106 { 'g', stats_pending_glines, 1, 0 },
107 { 'G', stats_glines, 1, 0 },
108 { 'h', stats_hooks, 1, 1 },
109 { 'H', stats_hubleaf, 1, 0 },
110 { 'i', stats_auth, 0, 0 },
111 { 'I', stats_auth, 0, 0 },
112 { 'k', stats_tklines, 0, 0 },
113 { 'K', stats_klines, 0, 0 },
114 { 'l', stats_ltrace, 1, 0 },
115 { 'L', stats_ltrace, 1, 0 },
116 { 'm', stats_messages, 0, 0 },
117 { 'M', stats_messages, 0, 0 },
118 { 'o', stats_oper, 0, 0 },
119 { 'O', stats_oper, 0, 0 },
120 { 'p', stats_operedup, 0, 0 },
121 { 'P', stats_ports, 0, 0 },
122 { 'q', stats_resv, 1, 0 },
123 { 'Q', stats_resv, 1, 0 },
124 { 'r', stats_usage, 1, 0 },
125 { 'R', stats_usage, 1, 0 },
126 { 'S', stats_service, 1, 0 },
127 { 't', stats_tstats, 1, 0 },
128 { 'T', stats_tstats, 1, 0 },
129 { 'u', stats_uptime, 0, 0 },
130 { 'U', stats_shared, 1, 0 },
131 { 'v', stats_servers, 1, 0 },
132 { 'V', stats_gdeny, 1, 0 },
133 { 'x', stats_gecos, 1, 0 },
134 { 'X', stats_gecos, 1, 0 },
135 { 'y', stats_class, 1, 0 },
136 { 'Y', stats_class, 1, 0 },
137 { 'z', stats_memory, 1, 0 },
138 { '?', stats_servlinks, 0, 0 },
139 { '\0', NULL, 0, 0 }
140 };
141
142 const char *from, *to;
143
144 static void
145 do_stats(struct Client *source_p, int parc, char *parv[])
146 {
147 const struct StatsStruct *tab = stats_cmd_table;
148 char statchar = *parv[1];
149
150 if (statchar == '\0')
151 {
152 sendto_one(source_p, form_str(RPL_ENDOFSTATS),
153 from, to, '*');
154 return;
155 }
156
157 for (; tab->handler; ++tab)
158 {
159 if (tab->letter == statchar)
160 {
161 /* The stats table says what privs are needed, so check --fl_ */
162 if ((tab->need_admin && !HasUMode(source_p, UMODE_ADMIN)) ||
163 (tab->need_oper && !HasUMode(source_p, UMODE_OPER)))
164 {
165 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
166 from, to);
167 break;
168 }
169
170 /* Blah, stats L needs the parameters, none of the others do.. */
171 if (statchar == 'L' || statchar == 'l')
172 {
173 sendto_realops_flags(UMODE_SPY, L_ALL,
174 "STATS %c requested by %s (%s@%s) [%s] on %s",
175 statchar, source_p->name, source_p->username,
176 source_p->host, source_p->servptr->name,
177 parc > 2 ? parv[2] : "<no recipient>");
178 tab->handler(source_p, parc, parv);
179 }
180 else
181 {
182 sendto_realops_flags(UMODE_SPY, L_ALL,
183 "STATS %c requested by %s (%s@%s) [%s]",
184 statchar, source_p->name, source_p->username,
185 source_p->host, source_p->servptr->name);
186 tab->handler(source_p);
187 }
188
189 break;
190 }
191 }
192
193 sendto_one(source_p, form_str(RPL_ENDOFSTATS),
194 from, to, statchar);
195 }
196
197 /*
198 * m_stats()
199 * parv[0] = sender prefix
200 * parv[1] = stat letter/command
201 * parv[2] = (if present) server/mask in stats L
202 *
203 * This will search the tables for the appropriate stats letter/command,
204 * if found execute it.
205 */
206 static void
207 m_stats(struct Client *client_p, struct Client *source_p,
208 int parc, char *parv[])
209 {
210 static time_t last_used = 0;
211
212 /* Is the stats meant for us? */
213 if (!ConfigFileEntry.disable_remote)
214 if (hunt_server(client_p, source_p, ":%s STATS %s :%s", 2,
215 parc, parv) != HUNTED_ISME)
216 return;
217
218 if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
219 {
220 from = me.id;
221 to = source_p->id;
222 }
223 else
224 {
225 from = me.name;
226 to = source_p->name;
227 }
228
229 /* Check the user is actually allowed to do /stats, and isnt flooding */
230 if ((last_used + ConfigFileEntry.pace_wait) > CurrentTime)
231 {
232 sendto_one(source_p,form_str(RPL_LOAD2HI),
233 from, to);
234 return;
235 }
236
237 last_used = CurrentTime;
238
239 do_stats(source_p, parc, parv);
240 }
241
242 /*
243 * mo_stats()
244 * parv[0] = sender prefix
245 * parv[1] = stat letter/command
246 * parv[2] = (if present) server/mask in stats L, or target
247 *
248 * This will search the tables for the appropriate stats letter,
249 * if found execute it.
250 */
251 static void
252 mo_stats(struct Client *client_p, struct Client *source_p,
253 int parc, char *parv[])
254 {
255 if (hunt_server(client_p, source_p, ":%s STATS %s :%s", 2,
256 parc, parv) != HUNTED_ISME)
257 return;
258
259 if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
260 {
261 from = me.id;
262 to = source_p->id;
263 }
264 else
265 {
266 from = me.name;
267 to = source_p->name;
268 }
269
270 do_stats(source_p, parc, parv);
271 }
272
273 /*
274 * ms_stats - STATS message handler
275 * parv[0] = sender prefix
276 * parv[1] = statistics selector (defaults to Message frequency)
277 * parv[2] = server name (current server defaulted, if omitted)
278 */
279 static void
280 ms_stats(struct Client *client_p, struct Client *source_p,
281 int parc, char *parv[])
282 {
283 if (hunt_server(client_p, source_p, ":%s STATS %s :%s", 2,
284 parc, parv) != HUNTED_ISME)
285 return;
286
287 if (IsClient(source_p))
288 mo_stats(client_p, source_p, parc, parv);
289 }
290
291 /*
292 * This is part of the STATS replies. There is no offical numeric for this
293 * since this isnt an official command, in much the same way as HASH isnt.
294 * It is also possible that some systems wont support this call or have
295 * different field names for "struct rusage".
296 * -avalon
297 */
298 static void
299 send_usage(struct Client *source_p)
300 {
301 struct rusage rus;
302 time_t secs;
303 time_t rup;
304 #ifdef hz
305 # define hzz hz
306 #else
307 # ifdef HZ
308 # define hzz HZ
309 # else
310 int hzz = 1;
311 # endif
312 #endif
313
314 if (getrusage(RUSAGE_SELF, &rus) == -1)
315 {
316 sendto_one(source_p, ":%s NOTICE %s :Getruseage error: %s",
317 me.name, source_p->name, strerror(errno));
318 return;
319 }
320
321 secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec;
322
323 if (secs == 0)
324 secs = 1;
325
326 rup = (CurrentTime - me.localClient->since) * hzz;
327
328 if (rup == 0)
329 rup = 1;
330
331 sendto_one(source_p,
332 ":%s %d %s R :CPU Secs %d:%d User %d:%d System %d:%d",
333 me.name, RPL_STATSDEBUG, source_p->name, (int)(secs/60), (int)(secs%60),
334 (int)(rus.ru_utime.tv_sec/60), (int)(rus.ru_utime.tv_sec%60),
335 (int)(rus.ru_stime.tv_sec/60), (int)(rus.ru_stime.tv_sec%60));
336 sendto_one(source_p, ":%s %d %s R :RSS %ld ShMem %ld Data %ld Stack %ld",
337 me.name, RPL_STATSDEBUG, source_p->name, rus.ru_maxrss,
338 (rus.ru_ixrss / rup), (rus.ru_idrss / rup),
339 (rus.ru_isrss / rup));
340 sendto_one(source_p, ":%s %d %s R :Swaps %d Reclaims %d Faults %d",
341 me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_nswap,
342 (int)rus.ru_minflt, (int)rus.ru_majflt);
343 sendto_one(source_p, ":%s %d %s R :Block in %d out %d",
344 me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_inblock,
345 (int)rus.ru_oublock);
346 sendto_one(source_p, ":%s %d %s R :Msg Rcv %d Send %d",
347 me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_msgrcv,
348 (int)rus.ru_msgsnd);
349 sendto_one(source_p, ":%s %d %s R :Signals %d Context Vol. %d Invol %d",
350 me.name, RPL_STATSDEBUG, source_p->name, (int)rus.ru_nsignals,
351 (int)rus.ru_nvcsw, (int)rus.ru_nivcsw);
352 }
353
354 static void
355 count_memory(struct Client *source_p)
356 {
357 const dlink_node *gptr = NULL;
358 const dlink_node *dlink = NULL;
359
360 unsigned int local_client_conf_count = 0; /* local client conf links */
361 unsigned int users_counted = 0; /* user structs */
362
363 unsigned int channel_members = 0;
364 unsigned int channel_invites = 0;
365 unsigned int channel_bans = 0;
366 unsigned int channel_except = 0;
367 unsigned int channel_invex = 0;
368
369 unsigned int wwu = 0; /* whowas users */
370 unsigned int class_count = 0; /* classes */
371 unsigned int aways_counted = 0;
372 unsigned int number_ips_stored; /* number of ip addresses hashed */
373
374 uint64_t channel_memory = 0;
375 uint64_t channel_ban_memory = 0;
376 uint64_t channel_except_memory = 0;
377 uint64_t channel_invex_memory = 0;
378
379 unsigned int safelist_count = 0;
380 uint64_t safelist_memory = 0;
381
382 uint64_t away_memory = 0; /* memory used by aways */
383 uint64_t wwm = 0; /* whowas array memory used */
384 uint64_t conf_memory = 0; /* memory used by conf lines */
385 uint64_t mem_ips_stored; /* memory used by ip address hash */
386
387 uint64_t total_channel_memory = 0;
388 uint64_t totww = 0;
389
390 unsigned int local_client_count = 0;
391 unsigned int remote_client_count = 0;
392
393 uint64_t local_client_memory_used = 0;
394 uint64_t remote_client_memory_used = 0;
395
396 uint64_t total_memory = 0;
397 unsigned int topic_count = 0;
398
399 unsigned int watch_list_headers = 0; /* watchlist headers */
400 unsigned int watch_list_entries = 0; /* watchlist entries */
401 uint64_t watch_list_memory = 0; /* watchlist memory used */
402
403
404 DLINK_FOREACH(gptr, global_client_list.head)
405 {
406 struct Client *target_p = gptr->data;
407
408 if (MyConnect(target_p))
409 {
410 ++local_client_count;
411 local_client_conf_count += dlink_list_length(&target_p->localClient->confs);
412 watch_list_entries += dlink_list_length(&target_p->localClient->watches);
413 }
414 else
415 ++remote_client_count;
416
417 if (IsClient(target_p))
418 {
419 ++users_counted;
420
421 if (target_p->away != NULL)
422 {
423 ++aways_counted;
424 away_memory += strlen(target_p->away) + 1;
425 }
426 }
427 }
428
429 /* Count up all channels, ban lists, except lists, Invex lists */
430 channel_memory = dlink_list_length(&global_channel_list) *
431 sizeof(struct Channel);
432 DLINK_FOREACH(gptr, global_channel_list.head)
433 {
434 const struct Ban *actualBan;
435 const struct Channel *chptr = gptr->data;
436
437 channel_members += dlink_list_length(&chptr->members);
438 channel_invites += dlink_list_length(&chptr->invites);
439
440 if (chptr->topic[0])
441 ++topic_count;
442
443 channel_bans += dlink_list_length(&chptr->banlist);
444 channel_ban_memory += dlink_list_length(&chptr->banlist) * sizeof(struct Ban);
445
446 DLINK_FOREACH(dlink, chptr->banlist.head)
447 {
448 actualBan = dlink->data;
449 assert(actualBan->who);
450
451 channel_ban_memory += actualBan->len + 1;
452 channel_ban_memory += strlen(actualBan->who) + 1;
453 }
454
455 channel_except += dlink_list_length(&chptr->exceptlist);
456 channel_except_memory += dlink_list_length(&chptr->exceptlist) * sizeof(struct Ban);
457
458 DLINK_FOREACH(dlink, chptr->exceptlist.head)
459 {
460 actualBan = dlink->data;
461 assert(actualBan->who);
462
463 channel_except_memory += actualBan->len + 1;
464 channel_except_memory += strlen(actualBan->who) + 1;
465 }
466
467 channel_invex += dlink_list_length(&chptr->invexlist);
468 channel_invex_memory += dlink_list_length(&chptr->invexlist) * sizeof(struct Ban);
469
470 DLINK_FOREACH(dlink, chptr->invexlist.head)
471 {
472 actualBan = dlink->data;
473 assert(actualBan->who);
474
475 channel_invex_memory += actualBan->len + 1;
476 channel_invex_memory += strlen(actualBan->who) + 1;
477 }
478 }
479
480 if ((safelist_count = dlink_list_length(&listing_client_list)))
481 {
482 safelist_memory = safelist_count * sizeof(struct ListTask);
483 DLINK_FOREACH(gptr, listing_client_list.head)
484 {
485 const struct Client *acptr = gptr->data;
486
487 DLINK_FOREACH(dlink, acptr->localClient->list_task->show_mask.head)
488 safelist_memory += strlen(dlink->data);
489
490 DLINK_FOREACH(dlink, acptr->localClient->list_task->hide_mask.head)
491 safelist_memory += strlen(dlink->data);
492 }
493 }
494
495 #if 0
496 /* XXX THIS has to be fixed !!!! -db */
497 /* count up all config items */
498 DLINK_FOREACH(dlink, ConfigItemList.head)
499 {
500 aconf = dlink->data;
501 conf_memory += aconf->host ? strlen(aconf->host)+1 : 0;
502 conf_memory += aconf->passwd ? strlen(aconf->passwd)+1 : 0;
503 conf_memory += aconf->name ? strlen(aconf->name)+1 : 0;
504 conf_memory += sizeof(struct AccessItem);
505 }
506 #endif
507 /* count up all classes */
508 class_count = dlink_list_length(&class_items);
509
510 count_whowas_memory(&wwu, &wwm);
511 watch_count_memory(&watch_list_headers, &watch_list_memory);
512
513 sendto_one(source_p, ":%s %d %s z :WATCH headers %u(%u) entries %d(%u)",
514 me.name, RPL_STATSDEBUG, source_p->name, watch_list_headers,
515 watch_list_memory, watch_list_entries,
516 watch_list_entries * sizeof(dlink_node) * 2);
517
518 sendto_one(source_p, ":%s %d %s z :Clients %u(%u)",
519 me.name, RPL_STATSDEBUG, source_p->name, users_counted,
520 (users_counted * sizeof(struct Client)));
521
522 sendto_one(source_p, ":%s %d %s z :User aways %u(%llu)",
523 me.name, RPL_STATSDEBUG, source_p->name,
524 aways_counted, away_memory);
525
526 sendto_one(source_p, ":%s %d %s z :Attached confs %u(%llu)",
527 me.name, RPL_STATSDEBUG, source_p->name,
528 local_client_conf_count,
529 (unsigned long long)(local_client_conf_count * sizeof(dlink_node)));
530
531 sendto_one(source_p, ":%s %d %s z :Resv channels %u(%lu) nicks %u(%lu)",
532 me.name, RPL_STATSDEBUG, source_p->name,
533 dlink_list_length(&resv_channel_list),
534 dlink_list_length(&resv_channel_list) * sizeof(struct ResvChannel),
535 dlink_list_length(&nresv_items),
536 dlink_list_length(&nresv_items) * sizeof(struct MatchItem));
537
538 sendto_one(source_p, ":%s %d %s z :Classes %u(%llu)",
539 me.name, RPL_STATSDEBUG, source_p->name,
540 class_count, (unsigned long long)(class_count * sizeof(struct ClassItem)));
541
542 sendto_one(source_p, ":%s %d %s z :Channels %uu(%llu) Topics %u(%u)",
543 me.name, RPL_STATSDEBUG, source_p->name,
544 dlink_list_length(&global_channel_list),
545 channel_memory, topic_count, topic_count *
546 (TOPICLEN + 1 + USERHOST_REPLYLEN));
547
548 sendto_one(source_p, ":%s %d %s z :Bans %u(%llu)",
549 me.name, RPL_STATSDEBUG, source_p->name,
550 channel_bans, channel_ban_memory);
551
552 sendto_one(source_p, ":%s %d %s z :Exceptions %u(%llu)",
553 me.name, RPL_STATSDEBUG, source_p->name,
554 channel_except, channel_except_memory);
555
556 sendto_one(source_p, ":%s %d %s z :Invex %u(%llu)",
557 me.name, RPL_STATSDEBUG, source_p->name,
558 channel_invex, channel_invex_memory);
559
560 sendto_one(source_p, ":%s %d %s z :Channel members %u(%llu) invites %u(%llu)",
561 me.name, RPL_STATSDEBUG, source_p->name, channel_members,
562 (unsigned long long)(channel_members * sizeof(struct Membership)),
563 channel_invites, (unsigned long long)channel_invites *
564 sizeof(dlink_node) * 2);
565
566 total_channel_memory = channel_memory + channel_ban_memory +
567 channel_members * sizeof(struct Membership) +
568 (channel_invites * sizeof(dlink_node)*2);
569
570 sendto_one(source_p, ":%s %d %s z :Safelist %u(%llu)",
571 me.name, RPL_STATSDEBUG, source_p->name,
572 safelist_count, safelist_memory);
573
574 sendto_one(source_p, ":%s %d %s z :Whowas users %u(%llu)",
575 me.name, RPL_STATSDEBUG, source_p->name,
576 wwu, (unsigned long long)(wwu * sizeof(struct Client)));
577
578 sendto_one(source_p, ":%s %d %s z :Whowas array %u(%llu)",
579 me.name, RPL_STATSDEBUG, source_p->name,
580 NICKNAMEHISTORYLENGTH, wwm);
581
582 totww = wwu * sizeof(struct Client) + wwm;
583
584 count_ip_hash(&number_ips_stored,&mem_ips_stored);
585 sendto_one(source_p, ":%s %d %s z :iphash %u(%llu)",
586 me.name, RPL_STATSDEBUG, source_p->name,
587 number_ips_stored, mem_ips_stored);
588
589 total_memory = totww + total_channel_memory + conf_memory + class_count *
590 sizeof(struct ClassItem);
591 sendto_one(source_p, ":%s %d %s z :Total: whowas %llu channel %llu conf %llu",
592 me.name, RPL_STATSDEBUG, source_p->name, totww,
593 total_channel_memory, conf_memory);
594
595 local_client_memory_used = local_client_count*(sizeof(struct Client) + sizeof(struct LocalUser));
596 total_memory += local_client_memory_used;
597 sendto_one(source_p, ":%s %d %s z :Local client Memory in use: %u(%llu)",
598 me.name, RPL_STATSDEBUG, source_p->name, local_client_count,
599 local_client_memory_used);
600
601 remote_client_memory_used = remote_client_count * sizeof(struct Client);
602 total_memory += remote_client_memory_used;
603 sendto_one(source_p, ":%s %d %s z :Remote client Memory in use: %u(%llu)",
604 me.name, RPL_STATSDEBUG, source_p->name, remote_client_count,
605 remote_client_memory_used);
606
607 block_heap_report_stats(source_p);
608
609 sendto_one(source_p,
610 ":%s %d %s z :TOTAL: %llu",
611 me.name, RPL_STATSDEBUG, source_p->name,
612 total_memory);
613 }
614
615 static void
616 stats_dns_servers(struct Client *source_p)
617 {
618 report_dns_servers(source_p);
619 }
620
621 static void
622 stats_connect(struct Client *source_p)
623 {
624 report_confitem_types(source_p, SERVER_TYPE, 0);
625 }
626
627 /* stats_deny()
628 *
629 * input - client to report to
630 * output - none
631 * side effects - client is given dline list.
632 */
633 static void
634 stats_deny(struct Client *source_p)
635 {
636 struct AddressRec *arec;
637 struct ConfItem *conf;
638 struct AccessItem *aconf;
639 int i;
640
641 for (i = 0; i < ATABLE_SIZE; i++)
642 {
643 for (arec = atable[i]; arec; arec=arec->next)
644 {
645 if (arec->type == CONF_DLINE)
646 {
647 aconf = arec->aconf;
648
649 /* dont report a tdline as a dline */
650 if (aconf->flags & CONF_FLAGS_TEMPORARY)
651 continue;
652
653 conf = unmap_conf_item(aconf);
654
655 sendto_one(source_p, form_str(RPL_STATSDLINE),
656 from, to, 'D', aconf->host, aconf->reason,
657 aconf->oper_reason);
658 }
659 }
660 }
661 }
662
663 /* stats_tdeny()
664 *
665 * input - client to report to
666 * output - none
667 * side effects - client is given dline list.
668 */
669 static void
670 stats_tdeny(struct Client *source_p)
671 {
672 struct AddressRec *arec;
673 struct ConfItem *conf;
674 struct AccessItem *aconf;
675 int i;
676
677 for (i = 0; i < ATABLE_SIZE; i++)
678 {
679 for (arec = atable[i]; arec; arec=arec->next)
680 {
681 if (arec->type == CONF_DLINE)
682 {
683 aconf = arec->aconf;
684
685 /* dont report a permanent dline as a tdline */
686 if (!(aconf->flags & CONF_FLAGS_TEMPORARY))
687 continue;
688
689 conf = unmap_conf_item(aconf);
690
691 sendto_one(source_p, form_str(RPL_STATSDLINE),
692 from, to, 'd', aconf->host, aconf->reason,
693 aconf->oper_reason);
694 }
695 }
696 }
697 }
698
699 /* stats_exempt()
700 *
701 * input - client to report to
702 * output - none
703 * side effects - client is given list of exempt blocks
704 */
705 static void
706 stats_exempt(struct Client *source_p)
707 {
708 struct AddressRec *arec;
709 struct ConfItem *conf;
710 struct AccessItem *aconf;
711 int i;
712
713 if (ConfigFileEntry.stats_e_disabled)
714 {
715 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
716 from, to);
717 return;
718 }
719
720 for (i = 0; i < ATABLE_SIZE; i++)
721 {
722 for (arec = atable[i]; arec; arec=arec->next)
723 {
724 if (arec->type == CONF_EXEMPTDLINE)
725 {
726 aconf = arec->aconf;
727
728 conf = unmap_conf_item(aconf);
729
730 sendto_one(source_p, form_str(RPL_STATSDLINE),
731 from, to, 'e', aconf->host,
732 aconf->reason, aconf->oper_reason);
733 }
734 }
735 }
736 }
737
738 static void
739 stats_events(struct Client *source_p)
740 {
741 show_events(source_p);
742 }
743
744 /* stats_pending_glines()
745 *
746 * input - client pointer
747 * output - none
748 * side effects - client is shown list of pending glines
749 */
750 static void
751 stats_pending_glines(struct Client *source_p)
752 {
753 const dlink_node *dn_ptr = NULL;
754 const struct gline_pending *glp_ptr = NULL;
755 char timebuffer[MAX_DATE_STRING] = { '\0' };
756 struct tm *tmptr = NULL;
757
758 if (!ConfigFileEntry.glines)
759 {
760 sendto_one(source_p, ":%s NOTICE %s :This server does not support G-Lines",
761 from, to);
762 return;
763 }
764
765 if (dlink_list_length(&pending_glines[GLINE_PENDING_ADD_TYPE]) > 0)
766 sendto_one(source_p, ":%s NOTICE %s :Pending G-lines",
767 from, to);
768
769 DLINK_FOREACH(dn_ptr, pending_glines[GLINE_PENDING_ADD_TYPE].head)
770 {
771 glp_ptr = dn_ptr->data;
772 tmptr = localtime(&glp_ptr->vote_1.time_request);
773 strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
774
775 sendto_one(source_p,
776 ":%s NOTICE %s :1) %s!%s@%s on %s requested gline at %s for %s@%s [%s]",
777 from, to, glp_ptr->vote_1.oper_nick,
778 glp_ptr->vote_1.oper_user, glp_ptr->vote_1.oper_host,
779 glp_ptr->vote_1.oper_server, timebuffer,
780 glp_ptr->user, glp_ptr->host, glp_ptr->vote_1.reason);
781
782 if (glp_ptr->vote_2.oper_nick[0] != '\0')
783 {
784 tmptr = localtime(&glp_ptr->vote_2.time_request);
785 strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
786 sendto_one(source_p,
787 ":%s NOTICE %s :2) %s!%s@%s on %s requested gline at %s for %s@%s [%s]",
788 from, to, glp_ptr->vote_2.oper_nick,
789 glp_ptr->vote_2.oper_user, glp_ptr->vote_2.oper_host,
790 glp_ptr->vote_2.oper_server, timebuffer,
791 glp_ptr->user, glp_ptr->host, glp_ptr->vote_2.reason);
792 }
793 }
794
795 sendto_one(source_p, ":%s NOTICE %s :End of Pending G-lines",
796 from, to);
797
798 if (dlink_list_length(&pending_glines[GLINE_PENDING_DEL_TYPE]) > 0)
799 sendto_one(source_p, ":%s NOTICE %s :Pending UNG-lines",
800 from, to);
801
802 DLINK_FOREACH(dn_ptr, pending_glines[GLINE_PENDING_DEL_TYPE].head)
803 {
804 glp_ptr = dn_ptr->data;
805 tmptr = localtime(&glp_ptr->vote_1.time_request);
806 strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
807
808 sendto_one(source_p,
809 ":%s NOTICE %s :1) %s!%s@%s on %s requested ungline at %s for %s@%s [%s]",
810 from, to, glp_ptr->vote_1.oper_nick,
811 glp_ptr->vote_1.oper_user, glp_ptr->vote_1.oper_host,
812 glp_ptr->vote_1.oper_server, timebuffer,
813 glp_ptr->user, glp_ptr->host, glp_ptr->vote_1.reason);
814
815 if (glp_ptr->vote_2.oper_nick[0] != '\0')
816 {
817 tmptr = localtime(&glp_ptr->vote_2.time_request);
818 strftime(timebuffer, MAX_DATE_STRING, "%Y/%m/%d %H:%M:%S", tmptr);
819 sendto_one(source_p,
820 ":%s NOTICE %s :2) %s!%s@%s on %s requested ungline at %s for %s@%s [%s]",
821 from, to, glp_ptr->vote_2.oper_nick,
822 glp_ptr->vote_2.oper_user, glp_ptr->vote_2.oper_host,
823 glp_ptr->vote_2.oper_server, timebuffer,
824 glp_ptr->user, glp_ptr->host, glp_ptr->vote_2.reason);
825
826 }
827 }
828
829 sendto_one(source_p, ":%s NOTICE %s :End of Pending UNG-lines",
830 from, to);
831 }
832
833 /* stats_glines()
834 *
835 * input - client pointer
836 * output - none
837 * side effects - client is shown list of glines
838 */
839 static void
840 stats_glines(struct Client *source_p)
841 {
842 struct AddressRec *arec = NULL;
843 int i = 0;
844
845 if (!ConfigFileEntry.glines)
846 {
847 sendto_one(source_p, ":%s NOTICE %s :This server does not support G-Lines",
848 from, to);
849 return;
850 }
851
852 for (; i < ATABLE_SIZE; ++i)
853 {
854 for (arec = atable[i]; arec; arec = arec->next)
855 {
856 if (arec->type == CONF_GLINE)
857 {
858 const struct AccessItem *aconf = arec->aconf;
859
860 sendto_one(source_p, form_str(RPL_STATSKLINE),
861 from, to, "G",
862 aconf->host ? aconf->host : "*",
863 aconf->user ? aconf->user : "*",
864 aconf->reason ? aconf->reason : "No reason", "" );
865 }
866 }
867 }
868 }
869
870 /* stats_gdeny()
871 *
872 * input - client pointer
873 * outputs - none
874 * side effects - client is shown gline ACL
875 */
876 static void
877 stats_gdeny(struct Client *source_p)
878 {
879 if (!ConfigFileEntry.glines)
880 {
881 sendto_one(source_p, ":%s NOTICE %s :This server does not support G-Lines",
882 from, to);
883 return;
884 }
885
886 report_confitem_types(source_p, GDENY_TYPE, 0);
887 }
888
889 static void
890 stats_hubleaf(struct Client *source_p)
891 {
892 report_confitem_types(source_p, HUB_TYPE, 0);
893 report_confitem_types(source_p, LEAF_TYPE, 0);
894 }
895
896 static void
897 stats_auth(struct Client *source_p)
898 {
899 /* Oper only, if unopered, return ERR_NOPRIVILEGES */
900 if ((ConfigFileEntry.stats_i_oper_only == 2) && !HasUMode(source_p, UMODE_OPER))
901 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
902 from, to);
903
904 /* If unopered, Only return matching auth blocks */
905 else if ((ConfigFileEntry.stats_i_oper_only == 1) && !HasUMode(source_p, UMODE_OPER))
906 {
907 struct ConfItem *conf;
908 struct AccessItem *aconf;
909
910 if (MyConnect(source_p))
911 aconf = find_conf_by_address(source_p->host,
912 &source_p->localClient->ip,
913 CONF_CLIENT,
914 source_p->localClient->aftype,
915 source_p->username,
916 source_p->localClient->passwd);
917 else
918 aconf = find_conf_by_address(source_p->host, NULL, CONF_CLIENT,
919 0, source_p->username, NULL);
920
921 if (aconf == NULL)
922 return;
923
924 conf = unmap_conf_item(aconf);
925
926 sendto_one(source_p, form_str(RPL_STATSILINE), from,
927 to, 'I',
928 "*", show_iline_prefix(source_p, aconf, aconf->user),
929 aconf->host, aconf->port,
930 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
931 }
932 /* They are opered, or allowed to see all auth blocks */
933 else
934 report_auth(source_p);
935 }
936
937 static void
938 stats_tklines(struct Client *source_p)
939 {
940 struct ConfItem *conf;
941 /* Oper only, if unopered, return ERR_NOPRIVILEGES */
942 if ((ConfigFileEntry.stats_k_oper_only == 2) && !HasUMode(source_p, UMODE_OPER))
943 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
944 from, to);
945
946 /* If unopered, Only return matching klines */
947 else if ((ConfigFileEntry.stats_k_oper_only == 1) && !HasUMode(source_p, UMODE_OPER))
948 {
949 struct AccessItem *aconf;
950
951 if (MyConnect(source_p))
952 aconf = find_conf_by_address(source_p->host,
953 &source_p->localClient->ip,
954 CONF_KILL,
955 source_p->localClient->aftype,
956 source_p->username, NULL);
957 else
958 aconf = find_conf_by_address(source_p->host, NULL, CONF_KILL,
959 0, source_p->username, NULL);
960
961 if (aconf == NULL)
962 return;
963
964 /* dont report a permanent kline as a tkline */
965 if (!(aconf->flags & CONF_FLAGS_TEMPORARY))
966 return;
967
968 conf = unmap_conf_item(aconf);
969
970 sendto_one(source_p, form_str(RPL_STATSKLINE), from,
971 to, "k", aconf->host, aconf->user, aconf->reason, "");
972 }
973 /* Theyre opered, or allowed to see all klines */
974 else {
975 report_Klines(source_p, 1);
976 report_confitem_types(source_p, RKLINE_TYPE, 1);
977 }
978 }
979
980 static void
981 stats_klines(struct Client *source_p)
982 {
983 /* Oper only, if unopered, return ERR_NOPRIVILEGES */
984 if ((ConfigFileEntry.stats_k_oper_only == 2) && !HasUMode(source_p, UMODE_OPER))
985 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
986 from, to);
987
988 /* If unopered, Only return matching klines */
989 else if ((ConfigFileEntry.stats_k_oper_only == 1) && !HasUMode(source_p, UMODE_OPER))
990 {
991 struct AccessItem *aconf;
992
993 /* search for a kline */
994 if (MyConnect(source_p))
995 aconf = find_conf_by_address(source_p->host,
996 &source_p->localClient->ip,
997 CONF_KILL,
998 source_p->localClient->aftype,
999 source_p->username, NULL);
1000 else
1001 aconf = find_conf_by_address(source_p->host, NULL, CONF_KILL,
1002 0, source_p->username, NULL);
1003
1004 if (aconf == NULL)
1005 return;
1006
1007 /* dont report a tkline as a kline */
1008 if (aconf->flags & CONF_FLAGS_TEMPORARY)
1009 return;
1010
1011 sendto_one(source_p, form_str(RPL_STATSKLINE), from,
1012 to, "K", aconf->host, aconf->user, aconf->reason,
1013 aconf->oper_reason);
1014 }
1015 /* Theyre opered, or allowed to see all klines */
1016 else {
1017 report_Klines(source_p, 0);
1018 report_confitem_types(source_p, RKLINE_TYPE, 0);
1019 }
1020 }
1021
1022 static void
1023 stats_messages(struct Client *source_p)
1024 {
1025 report_messages(source_p);
1026 }
1027
1028 static void
1029 stats_oper(struct Client *source_p)
1030 {
1031 if (!HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.stats_o_oper_only)
1032 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1033 from, to);
1034 else
1035 report_confitem_types(source_p, OPER_TYPE, 0);
1036 }
1037
1038 /* stats_operedup()
1039 *
1040 * input - client pointer
1041 * output - none
1042 * side effects - client is shown a list of active opers
1043 */
1044 static void
1045 stats_operedup(struct Client *source_p)
1046 {
1047 dlink_node *ptr;
1048
1049 DLINK_FOREACH(ptr, oper_list.head)
1050 {
1051 const struct Client *target_p = ptr->data;
1052
1053 if (HasUMode(target_p, UMODE_HIDDEN) && !HasUMode(source_p, UMODE_OPER))
1054 continue;
1055
1056 if (MyClient(source_p) && HasUMode(source_p, UMODE_OPER))
1057 sendto_one(source_p, ":%s %d %s p :[%c][%s] %s (%s@%s) Idle: %d",
1058 from, RPL_STATSDEBUG, to,
1059 HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O',
1060 oper_privs_as_string(target_p->localClient->operflags),
1061 target_p->name, target_p->username, target_p->host,
1062 (int)(CurrentTime - target_p->localClient->last_privmsg));
1063 else
1064 sendto_one(source_p, ":%s %d %s p :[%c] %s (%s@%s) Idle: %d",
1065 from, RPL_STATSDEBUG, to,
1066 HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O',
1067 target_p->name, target_p->username, target_p->host,
1068 (int)(CurrentTime - target_p->localClient->last_privmsg));
1069 }
1070
1071 sendto_one(source_p, ":%s %d %s p :%lu OPER(s)",
1072 from, RPL_STATSDEBUG, to, dlink_list_length(&oper_list));
1073 }
1074
1075 static void
1076 stats_ports(struct Client *source_p)
1077 {
1078 if (!HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.stats_P_oper_only)
1079 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1080 from, to);
1081 else
1082 show_ports(source_p);
1083 }
1084
1085 static void
1086 stats_resv(struct Client *source_p)
1087 {
1088 report_resv(source_p);
1089 }
1090
1091 static void
1092 stats_usage(struct Client *source_p)
1093 {
1094 send_usage(source_p);
1095 }
1096
1097 static void
1098 stats_service(struct Client *source_p)
1099 {
1100 report_confitem_types(source_p, SERVICE_TYPE, 0);
1101 }
1102
1103 static void
1104 stats_tstats(struct Client *source_p)
1105 {
1106 const struct Client *target_p = NULL;
1107 const dlink_node *ptr = NULL;
1108 struct ServerStatistics *sp;
1109 struct ServerStatistics tmp;
1110
1111 sp = &tmp;
1112 memcpy(sp, &ServerStats, sizeof(struct ServerStatistics));
1113
1114 /*
1115 * must use the += operator. is_sv is not the number of currently
1116 * active server connections. Note the incrementation in
1117 * s_bsd.c:close_connection.
1118 */
1119 sp->is_sv += dlink_list_length(&serv_list);
1120
1121 DLINK_FOREACH(ptr, serv_list.head)
1122 {
1123 target_p = ptr->data;
1124
1125 sp->is_sbs += target_p->localClient->send.bytes;
1126 sp->is_sbr += target_p->localClient->recv.bytes;
1127 sp->is_sti += CurrentTime - target_p->localClient->firsttime;
1128 }
1129
1130 sp->is_cl += dlink_list_length(&local_client_list);
1131
1132 DLINK_FOREACH(ptr, local_client_list.head)
1133 {
1134 target_p = ptr->data;
1135
1136 sp->is_cbs += target_p->localClient->send.bytes;
1137 sp->is_cbr += target_p->localClient->recv.bytes;
1138 sp->is_cti += CurrentTime - target_p->localClient->firsttime;
1139 }
1140
1141 sp->is_ni += dlink_list_length(&unknown_list);
1142
1143 sendto_one(source_p, ":%s %d %s T :accepts %u refused %u",
1144 me.name, RPL_STATSDEBUG, source_p->name, sp->is_ac, sp->is_ref);
1145 sendto_one(source_p, ":%s %d %s T :unknown commands %u prefixes %u",
1146 me.name, RPL_STATSDEBUG, source_p->name, sp->is_unco, sp->is_unpf);
1147 sendto_one(source_p, ":%s %d %s T :nick collisions %u unknown closes %u",
1148 me.name, RPL_STATSDEBUG, source_p->name, sp->is_kill, sp->is_ni);
1149 sendto_one(source_p, ":%s %d %s T :wrong direction %u empty %u",
1150 me.name, RPL_STATSDEBUG, source_p->name, sp->is_wrdi, sp->is_empt);
1151 sendto_one(source_p, ":%s %d %s T :numerics seen %u",
1152 me.name, RPL_STATSDEBUG, source_p->name, sp->is_num);
1153 sendto_one(source_p, ":%s %d %s T :auth successes %u fails %u",
1154 me.name, RPL_STATSDEBUG, source_p->name, sp->is_asuc, sp->is_abad);
1155 sendto_one(source_p, ":%s %d %s T :Client Server",
1156 me.name, RPL_STATSDEBUG, source_p->name);
1157
1158 sendto_one(source_p, ":%s %d %s T :connected %u %u",
1159 me.name, RPL_STATSDEBUG, source_p->name,
1160 (unsigned int)sp->is_cl,
1161 (unsigned int)sp->is_sv);
1162 sendto_one(source_p, ":%s %d %s T :bytes sent %llu %llu",
1163 me.name, RPL_STATSDEBUG, source_p->name,
1164 sp->is_cbs, sp->is_sbs);
1165 sendto_one(source_p, ":%s %d %s T :bytes recv %llu %llu",
1166 me.name, RPL_STATSDEBUG, source_p->name,
1167 sp->is_cbr, sp->is_sbr);
1168 sendto_one(source_p, ":%s %d %s T :time connected %u %u",
1169 me.name, RPL_STATSDEBUG, source_p->name,
1170 (unsigned int)sp->is_cti,
1171 (unsigned int)sp->is_sti);
1172 }
1173
1174 static void
1175 stats_uptime(struct Client *source_p)
1176 {
1177 time_t now = CurrentTime - me.localClient->since;
1178
1179 sendto_one(source_p, form_str(RPL_STATSUPTIME), from, to,
1180 now / 86400, (now / 3600) % 24, (now / 60) % 60, now % 60);
1181
1182 if (!ConfigFileEntry.disable_remote || HasUMode(source_p, UMODE_OPER))
1183 sendto_one(source_p, form_str(RPL_STATSCONN), from, to,
1184 Count.max_loc_con, Count.max_loc_cli, Count.totalrestartcount);
1185 }
1186
1187 static void
1188 stats_shared(struct Client *source_p)
1189 {
1190 report_confitem_types(source_p, ULINE_TYPE, 0);
1191 }
1192
1193 /* stats_servers()
1194 *
1195 * input - client pointer
1196 * output - none
1197 * side effects - client is shown lists of who connected servers
1198 */
1199 static void
1200 stats_servers(struct Client *source_p)
1201 {
1202 dlink_node *ptr = NULL;
1203
1204 DLINK_FOREACH(ptr, serv_list.head)
1205 {
1206 const struct Client *target_p = ptr->data;
1207
1208 sendto_one(source_p, ":%s %d %s v :%s (%s!%s@%s) Idle: %d",
1209 from, RPL_STATSDEBUG, to, target_p->name,
1210 (target_p->serv->by[0] ? target_p->serv->by : "Remote."),
1211 "*", "*", (int)(CurrentTime - target_p->localClient->lasttime));
1212 }
1213
1214 sendto_one(source_p, ":%s %d %s v :%u Server(s)",
1215 from, RPL_STATSDEBUG, to, dlink_list_length(&serv_list));
1216 }
1217
1218 static void
1219 stats_gecos(struct Client *source_p)
1220 {
1221 report_confitem_types(source_p, XLINE_TYPE, 0);
1222 report_confitem_types(source_p, RXLINE_TYPE, 0);
1223 }
1224
1225 static void
1226 stats_class(struct Client *source_p)
1227 {
1228 report_confitem_types(source_p, CLASS_TYPE, 0);
1229 }
1230
1231 static void
1232 stats_memory(struct Client *source_p)
1233 {
1234 count_memory(source_p);
1235 }
1236
1237 static void
1238 stats_servlinks(struct Client *source_p)
1239 {
1240 uint64_t sendB = 0, recvB = 0;
1241 time_t uptime = 0;
1242 dlink_node *ptr = NULL;
1243
1244 if (ConfigServerHide.flatten_links && !HasUMode(source_p, UMODE_OPER))
1245 {
1246 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
1247 from, to);
1248 return;
1249 }
1250
1251 DLINK_FOREACH(ptr, serv_list.head)
1252 {
1253 struct Client *target_p = ptr->data;
1254
1255 sendB += target_p->localClient->send.bytes;
1256 recvB += target_p->localClient->recv.bytes;
1257
1258 /* ":%s 211 %s %s %u %u %llu %u %llu :%u %u %s" */
1259 sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1260 from, to,
1261 get_client_name(target_p, HasUMode(source_p, UMODE_ADMIN) ? SHOW_IP : MASK_IP),
1262 dbuf_length(&target_p->localClient->buf_sendq),
1263 target_p->localClient->send.messages,
1264 target_p->localClient->send.bytes >> 10,
1265 target_p->localClient->recv.messages,
1266 target_p->localClient->recv.bytes >> 10,
1267 (unsigned)(CurrentTime - target_p->localClient->firsttime),
1268 (CurrentTime > target_p->localClient->since) ? (unsigned)(CurrentTime - target_p->localClient->since): 0,
1269 HasUMode(source_p, UMODE_OPER) ? show_capabilities(target_p) : "TS");
1270 }
1271
1272 sendB >>= 10;
1273 recvB >>= 10;
1274
1275 sendto_one(source_p, ":%s %d %s ? :%u total server(s)",
1276 from, RPL_STATSDEBUG, to, dlink_list_length(&serv_list));
1277 sendto_one(source_p, ":%s %d %s ? :Sent total : %7.2f %s",
1278 from, RPL_STATSDEBUG, to,
1279 _GMKv(sendB), _GMKs(sendB));
1280 sendto_one(source_p, ":%s %d %s ? :Recv total : %7.2f %s",
1281 from, RPL_STATSDEBUG, to,
1282 _GMKv(recvB), _GMKs(recvB));
1283
1284 uptime = (CurrentTime - me.localClient->since);
1285
1286 sendto_one(source_p, ":%s %d %s ? :Server send: %7.2f %s (%4.1f K/s)",
1287 from, RPL_STATSDEBUG, to,
1288 _GMKv((me.localClient->send.bytes>>10)),
1289 _GMKs((me.localClient->send.bytes>>10)),
1290 (float)((float)((me.localClient->send.bytes) >> 10) /
1291 (float)uptime));
1292 sendto_one(source_p, ":%s %d %s ? :Server recv: %7.2f %s (%4.1f K/s)",
1293 from, RPL_STATSDEBUG, to,
1294 _GMKv((me.localClient->recv.bytes>>10)),
1295 _GMKs((me.localClient->recv.bytes>>10)),
1296 (float)((float)((me.localClient->recv.bytes) >> 10) /
1297 (float)uptime));
1298 }
1299
1300 static void
1301 stats_ltrace(struct Client *source_p, int parc, char *parv[])
1302 {
1303 int doall = 0;
1304 int wilds = 0;
1305 char *name = NULL;
1306 char statchar;
1307
1308 if ((name = parse_stats_args(parc, parv, &doall, &wilds)) != NULL)
1309 {
1310 statchar = parv[1][0];
1311
1312 stats_L(source_p, name, doall, wilds, statchar);
1313 }
1314 else
1315 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1316 from, to, "STATS");
1317 }
1318
1319 /*
1320 * stats_L
1321 *
1322 * inputs - pointer to client to report to
1323 * - doall flag
1324 * - wild card or not
1325 * output - NONE
1326 * side effects -
1327 */
1328 static void
1329 stats_L(struct Client *source_p,char *name,int doall,
1330 int wilds,char statchar)
1331 {
1332 stats_L_list(source_p, name, doall, wilds, &unknown_list, statchar);
1333 stats_L_list(source_p, name, doall, wilds, &local_client_list, statchar);
1334 stats_L_list(source_p, name, doall, wilds, &serv_list, statchar);
1335 }
1336
1337 static void
1338 stats_L_list(struct Client *source_p,char *name, int doall, int wilds,
1339 dlink_list *list,char statchar)
1340 {
1341 dlink_node *ptr;
1342 struct Client *target_p;
1343
1344 /*
1345 * send info about connections which match, or all if the
1346 * mask matches from. Only restrictions are on those who
1347 * are invisible not being visible to 'foreigners' who use
1348 * a wild card based search to list it.
1349 */
1350 DLINK_FOREACH(ptr, list->head)
1351 {
1352 target_p = ptr->data;
1353
1354 if (HasUMode(target_p, UMODE_INVISIBLE) && (doall || wilds) &&
1355 !(MyConnect(source_p) && HasUMode(source_p, UMODE_OPER)) &&
1356 !HasUMode(target_p, UMODE_OPER) && (target_p != source_p))
1357 continue;
1358 if (!doall && wilds && !match(name, target_p->name))
1359 continue;
1360 if (!(doall || wilds) && irccmp(name, target_p->name))
1361 continue;
1362
1363 /* This basically shows ips for our opers if its not a server/admin, or
1364 * its one of our admins. */
1365 if(MyClient(source_p) && HasUMode(source_p, UMODE_OPER) &&
1366 (HasUMode(source_p, UMODE_ADMIN) ||
1367 (!IsServer(target_p) && !HasUMode(target_p, UMODE_ADMIN) &&
1368 !IsHandshake(target_p) && !IsConnecting(target_p))))
1369 {
1370 sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1371 from, to,
1372 (IsUpper(statchar)) ?
1373 get_client_name(target_p, SHOW_IP) :
1374 get_client_name(target_p, HIDE_IP),
1375 dbuf_length(&target_p->localClient->buf_sendq),
1376 target_p->localClient->send.messages,
1377 target_p->localClient->send.bytes>>10,
1378 target_p->localClient->recv.messages,
1379 target_p->localClient->recv.bytes>>10,
1380 (unsigned)(CurrentTime - target_p->localClient->firsttime),
1381 (CurrentTime > target_p->localClient->since) ? (unsigned)(CurrentTime - target_p->localClient->since):0,
1382 IsServer(target_p) ? show_capabilities(target_p) : "-");
1383 }
1384 else
1385 {
1386 /* If its a hidden ip, an admin, or a server, mask the real IP */
1387 if(IsIPSpoof(target_p) || IsServer(target_p) || HasUMode(target_p, UMODE_ADMIN)
1388 || IsHandshake(target_p) || IsConnecting(target_p))
1389 sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1390 from, to,
1391 get_client_name(target_p, MASK_IP),
1392 dbuf_length(&target_p->localClient->buf_sendq),
1393 target_p->localClient->send.messages,
1394 target_p->localClient->send.bytes>>10,
1395 target_p->localClient->recv.messages,
1396 target_p->localClient->recv.bytes>>10,
1397 (unsigned)(CurrentTime - target_p->localClient->firsttime),
1398 (CurrentTime > target_p->localClient->since) ? (unsigned)(CurrentTime - target_p->localClient->since):0,
1399 IsServer(target_p) ? show_capabilities(target_p) : "-");
1400 else /* show the real IP */
1401 sendto_one(source_p, form_str(RPL_STATSLINKINFO),
1402 from, to,
1403 (IsUpper(statchar)) ?
1404 get_client_name(target_p, SHOW_IP) :
1405 get_client_name(target_p, HIDE_IP),
1406 dbuf_length(&target_p->localClient->buf_sendq),
1407 target_p->localClient->send.messages,
1408 target_p->localClient->send.bytes>>10,
1409 target_p->localClient->recv.messages,
1410 target_p->localClient->recv.bytes>>10,
1411 (unsigned)(CurrentTime - target_p->localClient->firsttime),
1412 (CurrentTime > target_p->localClient->since) ? (unsigned)(CurrentTime - target_p->localClient->since):0,
1413 IsServer(target_p) ? show_capabilities(target_p) : "-");
1414 }
1415 }
1416 }
1417
1418 /* parse_stats_args()
1419 *
1420 * inputs - arg count
1421 * - args
1422 * - doall flag
1423 * - wild card or not
1424 * output - pointer to name to use
1425 * side effects -
1426 * common parse routine for m_stats args
1427 *
1428 */
1429 static char *
1430 parse_stats_args(int parc, char *parv[], int *doall, int *wilds)
1431 {
1432 char *name;
1433
1434 if (parc > 2)
1435 {
1436 name = parv[2];
1437
1438 if (!irccmp(name, from))
1439 *doall = 2;
1440 else if (match(name, from))
1441 *doall = 1;
1442
1443 if (strchr(name, '*') ||
1444 strchr(name, '?'))
1445 *wilds = 1;
1446
1447 return(name);
1448 }
1449 else
1450 return(NULL);
1451 }
1452
1453 static struct Message stats_msgtab = {
1454 "STATS", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
1455 { m_unregistered, m_stats, ms_stats, m_ignore, mo_stats, m_ignore }
1456 };
1457
1458 static void
1459 module_init(void)
1460 {
1461 mod_add_cmd(&stats_msgtab);
1462 }
1463
1464 static void
1465 module_exit(void)
1466 {
1467 mod_del_cmd(&stats_msgtab);
1468 }
1469
1470 struct module module_entry = {
1471 .node = { NULL, NULL, NULL },
1472 .name = NULL,
1473 .version = "$Revision$",
1474 .handle = NULL,
1475 .modinit = module_init,
1476 .modexit = module_exit,
1477 .flags = 0
1478 };

Properties

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