ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_stats.c
Revision: 1457
Committed: Wed Jul 4 19:44:26 2012 UTC (14 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/m_stats.c
File size: 50138 byte(s)
Log Message:
- m_stats.c: minor cleanups; remove useless wrapper functions, etc.

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

Properties

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