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 30 by adx, Sun Oct 2 20:03:27 2005 UTC vs.
ircd-hybrid/trunk/modules/m_stats.c (file contents), Revision 2118 by michael, Sun May 26 11:49:51 2013 UTC

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

Comparing:
ircd-hybrid/modules/m_stats.c (property svn:keywords), Revision 30 by adx, Sun Oct 2 20:03:27 2005 UTC vs.
ircd-hybrid/trunk/modules/m_stats.c (property svn:keywords), Revision 2118 by michael, Sun May 26 11:49:51 2013 UTC

# Line 1 | Line 1
1 < "Id Revision"
1 > Id Revision

Diff Legend

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