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/modules/m_stats.c (file contents), Revision 33 by knight, Sun Oct 2 20:50:00 2005 UTC vs.
ircd-hybrid/trunk/modules/m_stats.c (file contents), Revision 1759 by michael, Thu Jan 17 20:39:20 2013 UTC

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

Diff Legend

– Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)