ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_stats.c
(Generate patch)

Comparing ircd-hybrid-8/modules/m_stats.c (file contents):
Revision 1400 by michael, Mon May 7 20:08:32 2012 UTC vs.
Revision 1457 by michael, Wed Jul 4 19:44:26 2012 UTC

# Line 50 | Line 50
50   #include "irc_res.h"
51  
52  
53 static char *parse_stats_args(int, char **, int *, int *);
54 static void stats_L(struct Client *, char *, int, int, char);
55 static void stats_L_list(struct Client *, char *, int, int, dlink_list *, char);
56 static void stats_dns_servers(struct Client *);
57 static void stats_connect(struct Client *);
58 static void stats_deny(struct Client *);
59 static void stats_tdeny(struct Client *);
60 static void stats_exempt(struct Client *);
61 static void stats_events(struct Client *);
62 static void stats_pending_glines(struct Client *);
63 static void stats_glines(struct Client *);
64 static void stats_gdeny(struct Client *);
65 static void stats_hubleaf(struct Client *);
66 static void stats_auth(struct Client *);
67 static void stats_tklines(struct Client *);
68 static void stats_klines(struct Client *);
69 static void stats_messages(struct Client *);
70 static void stats_oper(struct Client *);
71 static void stats_operedup(struct Client *);
72 static void stats_ports(struct Client *);
73 static void stats_resv(struct Client *);
74 static void stats_usage(struct Client *);
75 static void stats_service(struct Client *);
76 static void stats_tstats(struct Client *);
77 static void stats_uptime(struct Client *);
78 static void stats_shared(struct Client *);
79 static void stats_servers(struct Client *);
80 static void stats_gecos(struct Client *);
81 static void stats_class(struct Client *);
82 static void stats_memory(struct Client *);
83 static void stats_servlinks(struct Client *);
84 static void stats_ltrace(struct Client *, int, char **);
85
86 /* This table contains the possible stats items, in order:
87 * /stats name,  function to call, operonly? adminonly? /stats letter
88 * case only matters in the stats letter column.. -- fl_ */
89 static const struct StatsStruct
90 {
91  const unsigned char letter;
92  void (*handler)();
93  const unsigned int need_oper;
94  const unsigned int need_admin;
95 } stats_cmd_table[] = {
96  /* letter     function            need_oper need_admin */
97  { 'a',        stats_dns_servers,      1,      1       },
98  { 'A',        stats_dns_servers,      1,      1       },
99  { 'c',        stats_connect,          1,      0       },
100  { 'C',        stats_connect,          1,      0       },
101  { 'd',        stats_tdeny,            1,      0       },
102  { 'D',        stats_deny,             1,      0       },
103  { 'e',        stats_exempt,           1,      0       },
104  { 'E',        stats_events,           1,      1       },
105  { 'f',        fd_dump,                1,      1       },
106  { 'F',        fd_dump,                1,      1       },
107  { 'g',        stats_pending_glines,   1,      0       },
108  { 'G',        stats_glines,           1,      0       },
109  { 'h',        stats_hooks,            1,      1       },
110  { 'H',        stats_hubleaf,          1,      0       },
111  { 'i',        stats_auth,             0,      0       },
112  { 'I',        stats_auth,             0,      0       },
113  { 'k',        stats_tklines,          0,      0       },
114  { 'K',        stats_klines,           0,      0       },
115  { 'l',        stats_ltrace,           1,      0       },
116  { 'L',        stats_ltrace,           1,      0       },
117  { 'm',        stats_messages,         0,      0       },
118  { 'M',        stats_messages,         0,      0       },
119  { 'o',        stats_oper,             0,      0       },
120  { 'O',        stats_oper,             0,      0       },
121  { 'p',        stats_operedup,         0,      0       },
122  { 'P',        stats_ports,            0,      0       },
123  { 'q',        stats_resv,             1,      0       },
124  { 'Q',        stats_resv,             1,      0       },
125  { 'r',        stats_usage,            1,      0       },
126  { 'R',        stats_usage,            1,      0       },
127  { 'S',        stats_service,          1,      0       },
128  { 't',        stats_tstats,           1,      0       },
129  { 'T',        stats_tstats,           1,      0       },
130  { 'u',        stats_uptime,           0,      0       },
131  { 'U',        stats_shared,           1,      0       },
132  { 'v',        stats_servers,          1,      0       },
133  { 'V',        stats_gdeny,            1,      0       },
134  { 'x',        stats_gecos,            1,      0       },
135  { 'X',        stats_gecos,            1,      0       },
136  { 'y',        stats_class,            1,      0       },
137  { 'Y',        stats_class,            1,      0       },
138  { 'z',        stats_memory,           1,      0       },
139  { '?',        stats_servlinks,        0,      0       },
140  { '\0',       NULL,                   0,      0       }
141 };
142
53   const char *from, *to;
54  
145 static void
146 do_stats(struct Client *source_p, int parc, char *parv[])
147 {
148  const struct StatsStruct *tab = stats_cmd_table;
149  char statchar = *parv[1];
150
151  if (statchar == '\0')
152  {
153    sendto_one(source_p, form_str(RPL_ENDOFSTATS),
154               from, to, '*');
155    return;
156  }
157
158  for (; tab->handler; ++tab)
159  {
160    if (tab->letter == statchar)
161    {
162      /* The stats table says what privs are needed, so check --fl_ */
163      if ((tab->need_admin && !HasUMode(source_p, UMODE_ADMIN)) ||
164          (tab->need_oper && !HasUMode(source_p, UMODE_OPER)))
165      {
166        sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
167                   from, to);
168        break;
169      }
170
171      /* Blah, stats L needs the parameters, none of the others do.. */
172      if (statchar == 'L' || statchar == 'l')
173      {
174        sendto_realops_flags(UMODE_SPY, L_ALL,
175                             "STATS %c requested by %s (%s@%s) [%s] on %s",
176                             statchar, source_p->name, source_p->username,
177                             source_p->host, source_p->servptr->name,
178                             parc > 2 ? parv[2] : "<no recipient>");
179        tab->handler(source_p, parc, parv);
180      }
181      else
182      {
183        sendto_realops_flags(UMODE_SPY, L_ALL,
184                             "STATS %c requested by %s (%s@%s) [%s]",
185                             statchar, source_p->name, source_p->username,
186                             source_p->host, source_p->servptr->name);
187        tab->handler(source_p);
188      }
189
190      break;
191    }
192  }
193
194  sendto_one(source_p, form_str(RPL_ENDOFSTATS),
195             from, to, statchar);
196 }
197
198 /*
199 * m_stats()
200 *      parv[0] = sender prefix
201 *      parv[1] = stat letter/command
202 *      parv[2] = (if present) server/mask in stats L
203 *
204 * This will search the tables for the appropriate stats letter/command,
205 * if found execute it.  
206 */
207 static void
208 m_stats(struct Client *client_p, struct Client *source_p,
209        int parc, char *parv[])
210 {
211  static time_t last_used = 0;
212
213  /* Is the stats meant for us? */
214  if (!ConfigFileEntry.disable_remote)
215    if (hunt_server(client_p, source_p, ":%s STATS %s :%s", 2,
216                    parc, parv) != HUNTED_ISME)
217      return;
218
219  if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
220  {
221    from = me.id;
222    to = source_p->id;
223  }
224  else
225  {
226    from = me.name;
227    to = source_p->name;
228  }
229
230  /* Check the user is actually allowed to do /stats, and isnt flooding */
231  if ((last_used + ConfigFileEntry.pace_wait) > CurrentTime)
232  {
233    sendto_one(source_p,form_str(RPL_LOAD2HI),
234               from, to);
235    return;
236  }
237
238  last_used = CurrentTime;
239
240  do_stats(source_p, parc, parv);
241 }
242
243 /*
244 * mo_stats()
245 *      parv[0] = sender prefix
246 *      parv[1] = stat letter/command
247 *      parv[2] = (if present) server/mask in stats L, or target
248 *
249 * This will search the tables for the appropriate stats letter,
250 * if found execute it.  
251 */
252 static void
253 mo_stats(struct Client *client_p, struct Client *source_p,
254         int parc, char *parv[])
255 {
256  if (hunt_server(client_p, source_p, ":%s STATS %s :%s", 2,
257                  parc, parv) != HUNTED_ISME)
258     return;
259
260  if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
261  {
262    from = me.id;
263    to = source_p->id;
264  }
265  else
266  {
267    from = me.name;
268    to = source_p->name;
269  }
270
271  do_stats(source_p, parc, parv);
272 }
273
274 /*
275 * ms_stats - STATS message handler
276 *      parv[0] = sender prefix
277 *      parv[1] = statistics selector (defaults to Message frequency)
278 *      parv[2] = server name (current server defaulted, if omitted)
279 */
280 static void
281 ms_stats(struct Client *client_p, struct Client *source_p,
282         int parc, char *parv[])
283 {
284  if (hunt_server(client_p, source_p, ":%s STATS %s :%s", 2,
285                  parc, parv) != HUNTED_ISME)
286    return;
287
288  if (IsClient(source_p))
289    mo_stats(client_p, source_p, parc, parv);
290 }
291
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.
# Line 297 | Line 60 | ms_stats(struct Client *client_p, struct
60   * -avalon
61   */
62   static void
63 < send_usage(struct Client *source_p)
63 > stats_usage(struct Client *source_p, int parc, char *parv[])
64   {
65    struct rusage rus;
66    time_t secs;
# Line 353 | Line 116 | send_usage(struct Client *source_p)
116   }
117  
118   static void
119 < count_memory(struct Client *source_p)
119 > stats_memory(struct Client *source_p, int parc, char *parv[])
120   {
121    const dlink_node *gptr = NULL;
122    const dlink_node *dlink = NULL;
# Line 620 | Line 383 | stats_dns_servers(struct Client *source_
383   }
384  
385   static void
386 < stats_connect(struct Client *source_p)
386 > stats_connect(struct Client *source_p, int parc, char *parv[])
387   {
388    report_confitem_types(source_p, SERVER_TYPE);
389   }
# Line 632 | Line 395 | stats_connect(struct Client *source_p)
395   * side effects - client is given dline list.
396   */
397   static void
398 < stats_deny(struct Client *source_p)
398 > stats_deny(struct Client *source_p, int parc, char *parv[])
399   {
400    struct ConfItem *conf;
401    struct AccessItem *aconf;
# Line 671 | Line 434 | stats_deny(struct Client *source_p)
434   * side effects - client is given dline list.
435   */
436   static void
437 < stats_tdeny(struct Client *source_p)
437 > stats_tdeny(struct Client *source_p, int parc, char *parv[])
438   {
439    struct ConfItem *conf;
440    struct AccessItem *aconf;
# Line 710 | Line 473 | stats_tdeny(struct Client *source_p)
473   * side effects - client is given list of exempt blocks
474   */
475   static void
476 < stats_exempt(struct Client *source_p)
476 > stats_exempt(struct Client *source_p, int parc, char *parv[])
477   {
478    struct ConfItem *conf;
479    struct AccessItem *aconf;
# Line 746 | Line 509 | stats_exempt(struct Client *source_p)
509   }
510  
511   static void
512 < stats_events(struct Client *source_p)
512 > stats_events(struct Client *source_p, int parc, char *parv[])
513   {
514    show_events(source_p);
515   }
# Line 758 | Line 521 | stats_events(struct Client *source_p)
521   * side effects - client is shown list of pending glines
522   */
523   static void
524 < stats_pending_glines(struct Client *source_p)
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;
# Line 847 | Line 610 | stats_pending_glines(struct Client *sour
610   * side effects - client is shown list of glines
611   */
612   static void
613 < stats_glines(struct Client *source_p)
613 > stats_glines(struct Client *source_p, int parc, char *parv[])
614   {
615    dlink_node *ptr = NULL;
616    unsigned int i = 0;
# Line 886 | Line 649 | stats_glines(struct Client *source_p)
649   * side effects - client is shown gline ACL
650   */
651   static void
652 < stats_gdeny(struct Client *source_p)
652 > stats_gdeny(struct Client *source_p, int parc, char *parv[])
653   {
654    if (!ConfigFileEntry.glines)
655    {
# Line 899 | Line 662 | stats_gdeny(struct Client *source_p)
662   }
663  
664   static void
665 < stats_hubleaf(struct Client *source_p)
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);
# Line 949 | Line 712 | show_iline_prefix(struct Client *sptr, s
712   }
713  
714   static void
715 < report_auth(struct Client *client_p)
715 > report_auth(struct Client *client_p, int parc, char *parv[])
716   {
717    struct ConfItem *conf;
718    struct AccessItem *aconf;
# Line 997 | Line 760 | report_auth(struct Client *client_p)
760   }
761  
762   static void
763 < stats_auth(struct Client *source_p)
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))
# Line 1034 | Line 797 | stats_auth(struct Client *source_p)
797    }
798    /* They are opered, or allowed to see all auth blocks */
799    else
800 <    report_auth(source_p);
800 >    report_auth(source_p, 0, NULL);
801   }
802  
803   /* report_Klines()
# Line 1083 | Line 846 | report_Klines(struct Client *client_p, i
846   }
847  
848   static void
849 < stats_tklines(struct Client *source_p)
849 > stats_tklines(struct Client *source_p, int parc, char *parv[])
850   {
851    struct ConfItem *conf;
852    /* Oper only, if unopered, return ERR_NOPRIVILEGES */
# Line 1125 | Line 888 | stats_tklines(struct Client *source_p)
888   }
889  
890   static void
891 < stats_klines(struct Client *source_p)
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))
# Line 1167 | Line 930 | stats_klines(struct Client *source_p)
930   }
931  
932   static void
933 < stats_messages(struct Client *source_p)
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)
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),
# Line 1189 | Line 952 | stats_oper(struct Client *source_p)
952   * side effects - client is shown a list of active opers
953   */
954   static void
955 < stats_operedup(struct Client *source_p)
955 > stats_operedup(struct Client *source_p, int parc, char *parv[])
956   {
957    dlink_node *ptr;
958  
# Line 1220 | Line 983 | stats_operedup(struct Client *source_p)
983   }
984  
985   static void
986 < stats_ports(struct Client *source_p)
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),
# Line 1230 | Line 993 | stats_ports(struct Client *source_p)
993   }
994  
995   static void
996 < stats_resv(struct Client *source_p)
996 > stats_resv(struct Client *source_p, int parc, char *parv[])
997   {
998    report_resv(source_p);
999   }
1000  
1001   static void
1002 < stats_usage(struct Client *source_p)
1240 < {
1241 <  send_usage(source_p);
1242 < }
1243 <
1244 < static void
1245 < stats_service(struct Client *source_p)
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)
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;
# Line 1319 | Line 1076 | stats_tstats(struct Client *source_p)
1076   }
1077  
1078   static void
1079 < stats_uptime(struct Client *source_p)
1079 > stats_uptime(struct Client *source_p, int parc, char *parv[])
1080   {
1081    time_t now = CurrentTime - me.localClient->since;
1082  
# Line 1332 | Line 1089 | stats_uptime(struct Client *source_p)
1089   }
1090  
1091   static void
1092 < stats_shared(struct Client *source_p)
1092 > stats_shared(struct Client *source_p, int parc, char *parv[])
1093   {
1094    report_confitem_types(source_p, ULINE_TYPE);
1095   }
# Line 1344 | Line 1101 | stats_shared(struct Client *source_p)
1101   * side effects - client is shown lists of who connected servers
1102   */
1103   static void
1104 < stats_servers(struct Client *source_p)
1104 > stats_servers(struct Client *source_p, int parc, char *parv[])
1105   {
1106    dlink_node *ptr = NULL;
1107  
# Line 1363 | Line 1120 | stats_servers(struct Client *source_p)
1120   }
1121  
1122   static void
1123 < stats_gecos(struct Client *source_p)
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)
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_memory(struct Client *source_p)
1380 < {
1381 <  count_memory(source_p);
1382 < }
1383 <
1384 < static void
1385 < stats_servlinks(struct Client *source_p)
1136 > stats_servlinks(struct Client *source_p, int parc, char *parv[])
1137   {
1138    uint64_t sendB = 0, recvB = 0;
1139    time_t uptime = 0;
# Line 1444 | Line 1195 | stats_servlinks(struct Client *source_p)
1195               (float)uptime));
1196   }
1197  
1198 < static void
1199 < stats_ltrace(struct Client *source_p, int parc, char *parv[])
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 <  int doall = 0;
1451 <  int wilds = 0;
1452 <  char *name = NULL;
1453 <  char statchar;
1212 >  char *name;
1213  
1214 <  if ((name = parse_stats_args(parc, parv, &doall, &wilds)) != NULL)
1214 >  if (parc > 2)
1215    {
1216 <    statchar = parv[1][0];
1216 >    name = parv[2];
1217  
1218 <    stats_L(source_p, name, doall, wilds, statchar);
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    }
1461  else
1462    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1463               from, to, "STATS");
1464 }
1227  
1228 < /*
1467 < * stats_L
1468 < *
1469 < * inputs       - pointer to client to report to
1470 < *              - doall flag
1471 < *              - wild card or not
1472 < * output       - NONE
1473 < * side effects -
1474 < */
1475 < static void
1476 < stats_L(struct Client *source_p,char *name,int doall,
1477 <        int wilds,char statchar)
1478 < {
1479 <  stats_L_list(source_p, name, doall, wilds, &unknown_list, statchar);
1480 <  stats_L_list(source_p, name, doall, wilds, &local_client_list, statchar);
1481 <  stats_L_list(source_p, name, doall, wilds, &serv_list, statchar);
1228 >  return NULL;
1229   }
1230  
1231   static void
# Line 1499 | Line 1246 | stats_L_list(struct Client *source_p,cha
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))
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;
# Line 1509 | Line 1256 | stats_L_list(struct Client *source_p,cha
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) &&
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) &&
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,
1265 >                 from, to,
1266                   (IsUpper(statchar)) ?
1267                   get_client_name(target_p, SHOW_IP) :
1268                   get_client_name(target_p, HIDE_IP),
# Line 1535 | Line 1282 | stats_L_list(struct Client *source_p,cha
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) : "-");
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) : "-");
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 < /* parse_stats_args()
1312 > /*
1313 > * stats_L
1314   *
1315 < * inputs       - arg count
1316 < *              - args
1317 < *              - doall flag
1318 < *              - wild card or not
1319 < * output       - pointer to name to use
1320 < * side effects -
1321 < * common parse routine for m_stats args
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 char *
1452 < parse_stats_args(int parc, char *parv[], int *doall, int *wilds)
1451 > static void
1452 > m_stats(struct Client *client_p, struct Client *source_p,
1453 >        int parc, char *parv[])
1454   {
1455 <  char *name;
1455 >  static time_t last_used = 0;
1456  
1457 <  if (parc > 2)
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 <    name = parv[2];
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 <    if (!irccmp(name, from))
1475 <      *doall = 2;
1476 <    else if (match(name, from))
1477 <      *doall = 1;
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 <    *wilds = has_wildcards(name);
1482 >  last_used = CurrentTime;
1483  
1484 <    return name;
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 <  return NULL;
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 = {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines