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

Comparing:
ircd-hybrid-8/src/conf.c (file contents), Revision 1381 by michael, Tue May 1 08:21:27 2012 UTC vs.
ircd-hybrid/trunk/src/conf.c (file contents), Revision 4114 by michael, Tue Jul 1 16:47:15 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  conf.c: Configuration file functions.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 18 | Line 17
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file conf.c
23 > * \brief Configuration file functions.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28   #include "list.h"
29   #include "ircd_defs.h"
28 #include "balloc.h"
30   #include "conf.h"
31 < #include "s_serv.h"
31 > #include "server.h"
32   #include "resv.h"
33   #include "channel.h"
34   #include "client.h"
35   #include "event.h"
35 #include "hook.h"
36   #include "irc_string.h"
37   #include "s_bsd.h"
38   #include "ircd.h"
# Line 43 | Line 43
43   #include "fdlist.h"
44   #include "log.h"
45   #include "send.h"
46 #include "s_gline.h"
46   #include "memory.h"
47 < #include "irc_res.h"
47 > #include "mempool.h"
48 > #include "res.h"
49   #include "userhost.h"
50 < #include "s_user.h"
50 > #include "user.h"
51   #include "channel_mode.h"
52   #include "parse.h"
53 < #include "s_misc.h"
53 > #include "misc.h"
54 > #include "conf_db.h"
55 > #include "conf_class.h"
56 > #include "motd.h"
57  
55 struct Callback *client_check_cb = NULL;
56 struct config_server_hide ConfigServerHide;
58  
59   /* general conf items link list root, other than k lines etc. */
60   dlink_list service_items = { NULL, NULL, 0 };
61   dlink_list server_items  = { NULL, NULL, 0 };
62   dlink_list cluster_items = { NULL, NULL, 0 };
62 dlink_list hub_items     = { NULL, NULL, 0 };
63 dlink_list leaf_items    = { NULL, NULL, 0 };
63   dlink_list oconf_items   = { NULL, NULL, 0 };
64   dlink_list uconf_items   = { NULL, NULL, 0 };
65   dlink_list xconf_items   = { NULL, NULL, 0 };
67 dlink_list rxconf_items  = { NULL, NULL, 0 };
68 dlink_list rkconf_items  = { NULL, NULL, 0 };
66   dlink_list nresv_items   = { NULL, NULL, 0 };
67 < dlink_list class_items   = { NULL, NULL, 0 };
71 < dlink_list gdeny_items   = { NULL, NULL, 0 };
72 <
73 < dlink_list temporary_xlines  = { NULL, NULL, 0 };
74 < dlink_list temporary_resv = { NULL, NULL, 0 };
67 > dlink_list cresv_items   = { NULL, NULL, 0 };
68  
69   extern unsigned int lineno;
70   extern char linebuf[];
71   extern char conffilebuf[IRCD_BUFSIZE];
72   extern int yyparse(); /* defined in y.tab.c */
73  
81 struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
82
74   /* internally defined functions */
75   static void read_conf(FILE *);
76   static void clear_out_old_conf(void);
86 static void flush_deleted_I_P(void);
77   static void expire_tklines(dlink_list *);
78   static void garbage_collect_ip_entries(void);
79   static int hash_ip(struct irc_ssaddr *);
80 < static int verify_access(struct Client *, const char *);
81 < static int attach_iline(struct Client *, struct ConfItem *);
80 > static int verify_access(struct Client *);
81 > static int attach_iline(struct Client *, struct MaskItem *);
82   static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
83 < static void parse_conf_file(int, int);
94 < static dlink_list *map_to_list(ConfType);
95 < static struct AccessItem *find_regexp_kline(const char *[]);
83 > static dlink_list *map_to_list(enum maskitem_type);
84   static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
85  
98 /*
99 * bit_len
100 */
101 static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
102 static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
103 static void destroy_cidr_class(struct ClassItem *);
104
105 static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
106
107 /* address of default class conf */
108 static struct ConfItem *class_default;
86  
87   /* usually, with hash tables, you use a prime number...
88   * but in this case I am dealing with ip addresses,
# Line 116 | Line 93 | static struct ConfItem *class_default;
93   struct ip_entry
94   {
95    struct irc_ssaddr ip;
96 <  int count;
97 <  time_t last_attempt;
96 >  unsigned int count;  /**< Number of registered users using this IP */
97 >  unsigned int connection_count;  /**< Number of connections from this IP in the last throttle_time duration */
98 >  time_t last_attempt;  /**< The last time someone connected from this IP */
99    struct ip_entry *next;
100   };
101  
102   static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
103 < static BlockHeap *ip_entry_heap = NULL;
103 > static mp_pool_t *ip_entry_pool = NULL;
104   static int ip_entries_count = 0;
105  
106  
129 void *
130 map_to_conf(struct ConfItem *aconf)
131 {
132  void *conf;
133  conf = (void *)((uintptr_t)aconf +
134                  (uintptr_t)sizeof(struct ConfItem));
135  return(conf);
136 }
137
138 struct ConfItem *
139 unmap_conf_item(void *aconf)
140 {
141  struct ConfItem *conf;
142
143  conf = (struct ConfItem *)((uintptr_t)aconf -
144                             (uintptr_t)sizeof(struct ConfItem));
145  return(conf);
146 }
147
107   /* conf_dns_callback()
108   *
109 < * inputs       - pointer to struct AccessItem
109 > * inputs       - pointer to struct MaskItem
110   *              - pointer to DNSReply reply
111   * output       - none
112   * side effects - called when resolver query finishes
# Line 158 | Line 117 | unmap_conf_item(void *aconf)
117   static void
118   conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
119   {
120 <  struct AccessItem *aconf = vptr;
120 >  struct MaskItem *conf = vptr;
121  
122 <  aconf->dns_pending = 0;
122 >  conf->dns_pending = 0;
123  
124 <  if (addr != NULL)
125 <    memcpy(&aconf->ipnum, addr, sizeof(aconf->ipnum));
124 >  if (addr)
125 >    memcpy(&conf->addr, addr, sizeof(conf->addr));
126    else
127 <    aconf->dns_failed = 1;
127 >    conf->dns_failed = 1;
128   }
129  
130   /* conf_dns_lookup()
# Line 175 | Line 134 | conf_dns_callback(void *vptr, const stru
134   * allocate a dns_query and start ns lookup.
135   */
136   static void
137 < conf_dns_lookup(struct AccessItem *aconf)
137 > conf_dns_lookup(struct MaskItem *conf)
138   {
139 <  if (!aconf->dns_pending)
139 >  if (!conf->dns_pending)
140    {
141 <    aconf->dns_pending = 1;
142 <    gethost_byname(conf_dns_callback, aconf, aconf->host);
141 >    conf->dns_pending = 1;
142 >    gethost_byname(conf_dns_callback, conf, conf->host);
143    }
144   }
145  
146 < /* make_conf_item()
147 < *
189 < * inputs       - type of item
190 < * output       - pointer to new conf entry
191 < * side effects - none
192 < */
193 < struct ConfItem *
194 < make_conf_item(ConfType type)
146 > struct MaskItem *
147 > conf_make(enum maskitem_type type)
148   {
149 <  struct ConfItem *conf = NULL;
150 <  struct AccessItem *aconf = NULL;
198 <  struct ClassItem *aclass = NULL;
199 <  int status = 0;
149 >  struct MaskItem *conf = MyCalloc(sizeof(*conf));
150 >  dlink_list *list = NULL;
151  
152 <  switch (type)
153 <  {
154 <  case DLINE_TYPE:
204 <  case EXEMPTDLINE_TYPE:
205 <  case GLINE_TYPE:
206 <  case KLINE_TYPE:
207 <  case CLIENT_TYPE:
208 <  case OPER_TYPE:
209 <  case SERVER_TYPE:
210 <    conf = MyMalloc(sizeof(struct ConfItem) +
211 <                    sizeof(struct AccessItem));
212 <    aconf = map_to_conf(conf);
213 <    aconf->aftype = AF_INET;
214 <
215 <    /* Yes, sigh. switch on type again */
216 <    switch (type)
217 <    {
218 <    case EXEMPTDLINE_TYPE:
219 <      status = CONF_EXEMPTDLINE;
220 <      break;
221 <
222 <    case DLINE_TYPE:
223 <      status = CONF_DLINE;
224 <      break;
225 <
226 <    case KLINE_TYPE:
227 <      status = CONF_KLINE;
228 <      break;
229 <
230 <    case GLINE_TYPE:
231 <      status = CONF_GLINE;
232 <      break;
233 <
234 <    case CLIENT_TYPE:
235 <      status = CONF_CLIENT;
236 <      break;
237 <
238 <    case OPER_TYPE:
239 <      status = CONF_OPERATOR;
240 <      dlinkAdd(conf, &conf->node, &oconf_items);
241 <      break;
242 <
243 <    case SERVER_TYPE:
244 <      status = CONF_SERVER;
245 <      dlinkAdd(conf, &conf->node, &server_items);
246 <      break;
247 <
248 <    default:
249 <      break;
250 <    }
251 <    aconf->status = status;
252 <    break;
253 <
254 <  case LEAF_TYPE:
255 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
256 <                                       sizeof(struct MatchItem));
257 <    dlinkAdd(conf, &conf->node, &leaf_items);
258 <    break;
259 <
260 <  case HUB_TYPE:
261 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
262 <                                       sizeof(struct MatchItem));
263 <    dlinkAdd(conf, &conf->node, &hub_items);
264 <    break;
265 <
266 <  case ULINE_TYPE:
267 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
268 <                                       sizeof(struct MatchItem));
269 <    dlinkAdd(conf, &conf->node, &uconf_items);
270 <    break;
271 <
272 <  case GDENY_TYPE:
273 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
274 <                                       sizeof(struct AccessItem));
275 <    dlinkAdd(conf, &conf->node, &gdeny_items);
276 <    break;
277 <
278 <  case XLINE_TYPE:
279 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
280 <                                       sizeof(struct MatchItem));
281 <    dlinkAdd(conf, &conf->node, &xconf_items);
282 <    break;
283 < #ifdef HAVE_LIBPCRE
284 <  case RXLINE_TYPE:
285 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
286 <                                       sizeof(struct MatchItem));
287 <    dlinkAdd(conf, &conf->node, &rxconf_items);
288 <    break;
289 <
290 <  case RKLINE_TYPE:
291 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
292 <                                       sizeof(struct AccessItem));
293 <    aconf = map_to_conf(conf);
294 <    aconf->status = CONF_KLINE;
295 <    dlinkAdd(conf, &conf->node, &rkconf_items);
296 <    break;
297 < #endif
298 <  case CLUSTER_TYPE:
299 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
300 <    dlinkAdd(conf, &conf->node, &cluster_items);
301 <    break;
302 <
303 <  case CRESV_TYPE:
304 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
305 <                                       sizeof(struct ResvChannel));
306 <    break;
307 <
308 <  case NRESV_TYPE:
309 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
310 <                                       sizeof(struct MatchItem));
311 <    dlinkAdd(conf, &conf->node, &nresv_items);
312 <    break;
313 <
314 <  case SERVICE_TYPE:
315 <    status = CONF_SERVICE;
316 <    conf = MyMalloc(sizeof(struct ConfItem));
317 <    dlinkAdd(conf, &conf->node, &service_items);
318 <    break;
319 <
320 <  case CLASS_TYPE:
321 <    conf = MyMalloc(sizeof(struct ConfItem) +
322 <                           sizeof(struct ClassItem));
323 <    dlinkAdd(conf, &conf->node, &class_items);
324 <
325 <    aclass = map_to_conf(conf);
326 <    aclass->active = 1;
327 <    aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
328 <    aclass->ping_freq = DEFAULT_PINGFREQUENCY;
329 <    aclass->max_total = MAXIMUM_LINKS_DEFAULT;
330 <    aclass->max_sendq = DEFAULT_SENDQ;
331 <
332 <    break;
333 <
334 <  default:
335 <    conf = NULL;
336 <    break;
337 <  }
338 <
339 <  /* XXX Yes, this will core if default is hit. I want it to for now - db */
340 <  conf->type = type;
152 >  conf->type   = type;
153 >  conf->active = 1;
154 >  conf->aftype = AF_INET;
155  
156 +  if ((list = map_to_list(type)))
157 +    dlinkAdd(conf, &conf->node, list);
158    return conf;
159   }
160  
161   void
162 < delete_conf_item(struct ConfItem *conf)
162 > conf_free(struct MaskItem *conf)
163   {
164 <  dlink_node *m = NULL;
165 <  struct MatchItem *match_item;
166 <  struct AccessItem *aconf;
167 <  ConfType type = conf->type;
164 >  dlink_node *ptr = NULL, *ptr_next = NULL;
165 >  dlink_list *list = NULL;
166 >
167 >  if (conf->node.next)
168 >    if ((list = map_to_list(conf->type)))
169 >      dlinkDelete(&conf->node, list);
170  
171    MyFree(conf->name);
354  conf->name = NULL;
172  
173 <  switch(type)
174 <  {
175 <  case DLINE_TYPE:
176 <  case EXEMPTDLINE_TYPE:
177 <  case GLINE_TYPE:
178 <  case KLINE_TYPE:
179 <  case CLIENT_TYPE:
180 <  case OPER_TYPE:
181 <  case SERVER_TYPE:
182 <    aconf = map_to_conf(conf);
183 <
184 <    if (aconf->dns_pending)
185 <      delete_resolver_queries(aconf);
186 <    if (aconf->passwd != NULL)
187 <      memset(aconf->passwd, 0, strlen(aconf->passwd));
371 <    if (aconf->spasswd != NULL)
372 <      memset(aconf->spasswd, 0, strlen(aconf->spasswd));
373 <    aconf->class_ptr = NULL;
374 <
375 <    MyFree(aconf->passwd);
376 <    MyFree(aconf->spasswd);
377 <    MyFree(aconf->reason);
378 <    MyFree(aconf->oper_reason);
379 <    MyFree(aconf->user);
380 <    MyFree(aconf->host);
381 <    MyFree(aconf->cipher_list);
173 >  if (conf->dns_pending)
174 >    delete_resolver_queries(conf);
175 >  if (conf->passwd)
176 >    memset(conf->passwd, 0, strlen(conf->passwd));
177 >  if (conf->spasswd)
178 >    memset(conf->spasswd, 0, strlen(conf->spasswd));
179 >
180 >  conf->class = NULL;
181 >
182 >  MyFree(conf->passwd);
183 >  MyFree(conf->spasswd);
184 >  MyFree(conf->reason);
185 >  MyFree(conf->certfp);
186 >  MyFree(conf->user);
187 >  MyFree(conf->host);
188   #ifdef HAVE_LIBCRYPTO
189 <    if (aconf->rsa_public_key)
384 <      RSA_free(aconf->rsa_public_key);
385 <    MyFree(aconf->rsa_public_key_file);
386 < #endif
189 >  MyFree(conf->cipher_list);
190  
191 <    /* Yes, sigh. switch on type again */
192 <    switch(type)
390 <    {
391 <    case EXEMPTDLINE_TYPE:
392 <    case DLINE_TYPE:
393 <    case GLINE_TYPE:
394 <    case KLINE_TYPE:
395 <    case CLIENT_TYPE:
396 <      MyFree(conf);
397 <      break;
398 <
399 <    case OPER_TYPE:
400 <      aconf = map_to_conf(conf);
401 <      if (!IsConfIllegal(aconf))
402 <        dlinkDelete(&conf->node, &oconf_items);
403 <      MyFree(conf);
404 <      break;
405 <
406 <    case SERVER_TYPE:
407 <      aconf = map_to_conf(conf);
408 <      if (!IsConfIllegal(aconf))
409 <        dlinkDelete(&conf->node, &server_items);
410 <      MyFree(conf);
411 <      break;
412 <
413 <    default:
414 <      break;
415 <    }
416 <    break;
417 <
418 <  case HUB_TYPE:
419 <    match_item = map_to_conf(conf);
420 <    MyFree(match_item->user);
421 <    MyFree(match_item->host);
422 <    MyFree(match_item->reason);
423 <    MyFree(match_item->oper_reason);
424 <    /* If marked illegal, its already been pulled off of the hub_items list */
425 <    if (!match_item->illegal)
426 <      dlinkDelete(&conf->node, &hub_items);
427 <    MyFree(conf);
428 <    break;
429 <
430 <  case LEAF_TYPE:
431 <    match_item = map_to_conf(conf);
432 <    MyFree(match_item->user);
433 <    MyFree(match_item->host);
434 <    MyFree(match_item->reason);
435 <    MyFree(match_item->oper_reason);
436 <    /* If marked illegal, its already been pulled off of the leaf_items list */
437 <    if (!match_item->illegal)
438 <      dlinkDelete(&conf->node, &leaf_items);
439 <    MyFree(conf);
440 <    break;
441 <
442 <  case ULINE_TYPE:
443 <    match_item = map_to_conf(conf);
444 <    MyFree(match_item->user);
445 <    MyFree(match_item->host);
446 <    MyFree(match_item->reason);
447 <    MyFree(match_item->oper_reason);
448 <    dlinkDelete(&conf->node, &uconf_items);
449 <    MyFree(conf);
450 <    break;
451 <
452 <  case XLINE_TYPE:
453 <    match_item = map_to_conf(conf);
454 <    MyFree(match_item->user);
455 <    MyFree(match_item->host);
456 <    MyFree(match_item->reason);
457 <    MyFree(match_item->oper_reason);
458 <    dlinkDelete(&conf->node, &xconf_items);
459 <    MyFree(conf);
460 <    break;
461 < #ifdef HAVE_LIBPCRE
462 <  case RKLINE_TYPE:
463 <    aconf = map_to_conf(conf);
464 <    MyFree(aconf->regexuser);
465 <    MyFree(aconf->regexhost);
466 <    MyFree(aconf->user);
467 <    MyFree(aconf->host);
468 <    MyFree(aconf->reason);
469 <    MyFree(aconf->oper_reason);
470 <    dlinkDelete(&conf->node, &rkconf_items);
471 <    MyFree(conf);
472 <    break;
473 <
474 <  case RXLINE_TYPE:
475 <    MyFree(conf->regexpname);
476 <    match_item = map_to_conf(conf);
477 <    MyFree(match_item->user);
478 <    MyFree(match_item->host);
479 <    MyFree(match_item->reason);
480 <    MyFree(match_item->oper_reason);
481 <    dlinkDelete(&conf->node, &rxconf_items);
482 <    MyFree(conf);
483 <    break;
191 >  if (conf->rsa_public_key)
192 >    RSA_free(conf->rsa_public_key);
193   #endif
194 <  case NRESV_TYPE:
195 <    match_item = map_to_conf(conf);
196 <    MyFree(match_item->user);
197 <    MyFree(match_item->host);
198 <    MyFree(match_item->reason);
490 <    MyFree(match_item->oper_reason);
491 <    dlinkDelete(&conf->node, &nresv_items);
492 <
493 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
494 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
495 <        free_dlink_node(m);
496 <
497 <    MyFree(conf);
498 <    break;
499 <
500 <  case GDENY_TYPE:
501 <    aconf = map_to_conf(conf);
502 <    MyFree(aconf->user);
503 <    MyFree(aconf->host);
504 <    dlinkDelete(&conf->node, &gdeny_items);
505 <    MyFree(conf);
506 <    break;
507 <
508 <  case CLUSTER_TYPE:
509 <    dlinkDelete(&conf->node, &cluster_items);
510 <    MyFree(conf);
511 <    break;
512 <
513 <  case CRESV_TYPE:
514 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
515 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
516 <        free_dlink_node(m);
517 <
518 <    MyFree(conf);
519 <    break;
520 <
521 <  case CLASS_TYPE:
522 <    dlinkDelete(&conf->node, &class_items);
523 <    MyFree(conf);
524 <    break;
525 <
526 <  case SERVICE_TYPE:
527 <    dlinkDelete(&conf->node, &service_items);
528 <    MyFree(conf);
529 <    break;
530 <
531 <  default:
532 <    break;
194 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->hub_list.head)
195 >  {
196 >    MyFree(ptr->data);
197 >    dlinkDelete(ptr, &conf->hub_list);
198 >    free_dlink_node(ptr);
199    }
534 }
535
536 /* free_access_item()
537 *
538 * inputs       - pointer to conf to free
539 * output       - none
540 * side effects - crucial password fields are zeroed, conf is freed
541 */
542 void
543 free_access_item(struct AccessItem *aconf)
544 {
545  struct ConfItem *conf;
546
547  if (aconf == NULL)
548    return;
549  conf = unmap_conf_item(aconf);
550  delete_conf_item(conf);
551 }
200  
201 < static const unsigned int shared_bit_table[] =
554 <  { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
555 <
556 < /* report_confitem_types()
557 < *
558 < * inputs       - pointer to client requesting confitem report
559 < *              - ConfType to report
560 < * output       - none
561 < * side effects -
562 < */
563 < void
564 < report_confitem_types(struct Client *source_p, ConfType type)
565 < {
566 <  dlink_node *ptr = NULL;
567 <  struct ConfItem *conf = NULL;
568 <  struct AccessItem *aconf = NULL;
569 <  struct MatchItem *matchitem = NULL;
570 <  struct ClassItem *classitem = NULL;
571 <  char buf[12];
572 <  char *p = NULL;
573 <
574 <  switch (type)
201 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->leaf_list.head)
202    {
203 <  case GDENY_TYPE:
204 <    DLINK_FOREACH(ptr, gdeny_items.head)
205 <    {
206 <      conf = ptr->data;
580 <      aconf = map_to_conf(conf);
581 <
582 <      p = buf;
583 <
584 <      if (aconf->flags & GDENY_BLOCK)
585 <        *p++ = 'B';
586 <      else
587 <        *p++ = 'b';
588 <
589 <      if (aconf->flags & GDENY_REJECT)
590 <        *p++ = 'R';
591 <      else
592 <        *p++ = 'r';
593 <
594 <      *p = '\0';
595 <
596 <      sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
597 <                 me.name, RPL_STATSDEBUG, source_p->name,
598 <                 aconf->user, aconf->host, conf->name, buf);
599 <    }
600 <    break;
601 <
602 <  case XLINE_TYPE:
603 <    DLINK_FOREACH(ptr, xconf_items.head)
604 <    {
605 <      conf = ptr->data;
606 <      matchitem = map_to_conf(conf);
607 <
608 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
609 <                 me.name, source_p->name,
610 <                 matchitem->hold ? "x": "X", matchitem->count,
611 <                 conf->name, matchitem->reason);
612 <    }
613 <    break;
614 <
615 < #ifdef HAVE_LIBPCRE
616 <  case RXLINE_TYPE:
617 <    DLINK_FOREACH(ptr, rxconf_items.head)
618 <    {
619 <      conf = ptr->data;
620 <      matchitem = map_to_conf(conf);
621 <
622 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
623 <                 me.name, source_p->name,
624 <                 "XR", matchitem->count,
625 <                 conf->name, matchitem->reason);
626 <    }
627 <    break;
628 <
629 <  case RKLINE_TYPE:
630 <    DLINK_FOREACH(ptr, rkconf_items.head)
631 <    {
632 <      aconf = map_to_conf((conf = ptr->data));
633 <
634 <      sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
635 <                 source_p->name, "KR", aconf->host, aconf->user,
636 <                 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
637 <    }
638 <    break;
639 < #endif
640 <
641 <  case ULINE_TYPE:
642 <    DLINK_FOREACH(ptr, uconf_items.head)
643 <    {
644 <      conf = ptr->data;
645 <      matchitem = map_to_conf(conf);
646 <
647 <      p = buf;
648 <
649 <      /* some of these are redundant for the sake of
650 <       * consistency with cluster{} flags
651 <       */
652 <      *p++ = 'c';
653 <      flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
654 <
655 <      sendto_one(source_p, form_str(RPL_STATSULINE),
656 <                 me.name, source_p->name, conf->name,
657 <                 matchitem->user?matchitem->user: "*",
658 <                 matchitem->host?matchitem->host: "*", buf);
659 <    }
660 <
661 <    DLINK_FOREACH(ptr, cluster_items.head)
662 <    {
663 <      conf = ptr->data;
664 <
665 <      p = buf;
666 <
667 <      *p++ = 'C';
668 <      flags_to_ascii(conf->flags, shared_bit_table, p, 0);
669 <
670 <      sendto_one(source_p, form_str(RPL_STATSULINE),
671 <                 me.name, source_p->name, conf->name,
672 <                 "*", "*", buf);
673 <    }
674 <
675 <    break;
676 <
677 <  case OPER_TYPE:
678 <    DLINK_FOREACH(ptr, oconf_items.head)
679 <    {
680 <      conf = ptr->data;
681 <      aconf = map_to_conf(conf);
682 <
683 <      /* Don't allow non opers to see oper privs */
684 <      if (HasUMode(source_p, UMODE_OPER))
685 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
686 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
687 <                   conf->name, oper_privs_as_string(aconf->port),
688 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
689 <      else
690 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
691 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
692 <                   conf->name, "0",
693 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
694 <    }
695 <    break;
696 <
697 <  case CLASS_TYPE:
698 <    DLINK_FOREACH(ptr, class_items.head)
699 <    {
700 <      conf = ptr->data;
701 <      classitem = map_to_conf(conf);
702 <      sendto_one(source_p, form_str(RPL_STATSYLINE),
703 <                 me.name, source_p->name, 'Y',
704 <                 conf->name, classitem->ping_freq,
705 <                 classitem->con_freq,
706 <                 classitem->max_total, classitem->max_sendq,
707 <                 classitem->curr_user_count,
708 <                 classitem->active ? "active" : "disabled");
709 <    }
710 <    break;
711 <
712 <  case CONF_TYPE:
713 <  case CLIENT_TYPE:
714 <    break;
715 <
716 <  case SERVICE_TYPE:
717 <    DLINK_FOREACH(ptr, service_items.head)
718 <    {
719 <      conf = ptr->data;
720 <      sendto_one(source_p, form_str(RPL_STATSSERVICE),
721 <                 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
722 <    }
723 <    break;
724 <
725 <  case SERVER_TYPE:
726 <    DLINK_FOREACH(ptr, server_items.head)
727 <    {
728 <      p = buf;
729 <
730 <      conf = ptr->data;
731 <      aconf = map_to_conf(conf);
732 <
733 <      buf[0] = '\0';
734 <
735 <      if (IsConfAllowAutoConn(aconf))
736 <        *p++ = 'A';
737 <      if (IsConfSSL(aconf))
738 <        *p++ = 'S';
739 <      if (IsConfTopicBurst(aconf))
740 <        *p++ = 'T';
741 <      if (buf[0] == '\0')
742 <        *p++ = '*';
743 <
744 <      *p = '\0';
745 <
746 <      /*
747 <       * Allow admins to see actual ips unless hide_server_ips is enabled
748 <       */
749 <      if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
750 <        sendto_one(source_p, form_str(RPL_STATSCLINE),
751 <                   me.name, source_p->name, 'C', aconf->host,
752 <                   buf, conf->name, aconf->port,
753 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
754 <        else
755 <          sendto_one(source_p, form_str(RPL_STATSCLINE),
756 <                     me.name, source_p->name, 'C',
757 <                     "*@127.0.0.1", buf, conf->name, aconf->port,
758 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
759 <    }
760 <    break;
761 <
762 <  case HUB_TYPE:
763 <    DLINK_FOREACH(ptr, hub_items.head)
764 <    {
765 <      conf = ptr->data;
766 <      matchitem = map_to_conf(conf);
767 <      sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
768 <                 source_p->name, 'H', matchitem->host, conf->name, 0, "*");
769 <    }
770 <    break;
203 >    MyFree(ptr->data);
204 >    dlinkDelete(ptr, &conf->leaf_list);
205 >    free_dlink_node(ptr);
206 >  }
207  
208 <  case LEAF_TYPE:
209 <    DLINK_FOREACH(ptr, leaf_items.head)
210 <    {
775 <      conf = ptr->data;
776 <      matchitem = map_to_conf(conf);
777 <      sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
778 <                 source_p->name, 'L', matchitem->host, conf->name, 0, "*");
779 <    }
780 <    break;
208 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->exempt_list.head)
209 >  {
210 >    struct exempt *exptr = ptr->data;
211  
212 <  case GLINE_TYPE:
213 <  case KLINE_TYPE:
214 <  case DLINE_TYPE:
215 <  case EXEMPTDLINE_TYPE:
216 <  case CRESV_TYPE:
787 <  case NRESV_TYPE:
788 <  case CLUSTER_TYPE:
789 <  default:
790 <    break;
212 >    dlinkDelete(ptr, &conf->exempt_list);
213 >    MyFree(exptr->name);
214 >    MyFree(exptr->user);
215 >    MyFree(exptr->host);
216 >    MyFree(exptr);
217    }
218 +
219 +  MyFree(conf);
220   }
221  
222   /* check_client()
# Line 804 | Line 232 | report_confitem_types(struct Client *sou
232   *                Look for conf lines which have the same
233   *                status as the flags passed.
234   */
235 < static void *
236 < check_client(va_list args)
235 > int
236 > check_client(struct Client *source_p)
237   {
810  struct Client *source_p = va_arg(args, struct Client *);
811  const char *username = va_arg(args, const char *);
238    int i;
239 <
240 <  /* I'm already in big trouble if source_p->localClient is NULL -db */
241 <  if ((i = verify_access(source_p, username)))
816 <    ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
239 >
240 >  if ((i = verify_access(source_p)))
241 >    ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
242           source_p->name, source_p->sockhost);
243  
244    switch (i)
245    {
246      case TOO_MANY:
247 <      sendto_realops_flags(UMODE_FULL, L_ALL,
247 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
248                             "Too many on IP for %s (%s).",
249 <                           get_client_name(source_p, SHOW_IP),
250 <                           source_p->sockhost);
249 >                           get_client_name(source_p, SHOW_IP),
250 >                           source_p->sockhost);
251        ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
252 <           get_client_name(source_p, SHOW_IP));
252 >           get_client_name(source_p, SHOW_IP));
253        ++ServerStats.is_ref;
254 <      exit_client(source_p, &me, "No more connections allowed on that IP");
254 >      exit_client(source_p, "No more connections allowed on that IP");
255        break;
256  
257      case I_LINE_FULL:
258 <      sendto_realops_flags(UMODE_FULL, L_ALL,
259 <                           "I-line is full for %s (%s).",
260 <                           get_client_name(source_p, SHOW_IP),
261 <                           source_p->sockhost);
258 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
259 >                           "auth{} block is full for %s (%s).",
260 >                           get_client_name(source_p, SHOW_IP),
261 >                           source_p->sockhost);
262        ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
263 <           get_client_name(source_p, SHOW_IP));
263 >           get_client_name(source_p, SHOW_IP));
264        ++ServerStats.is_ref;
265 <      exit_client(source_p, &me,
841 <                "No more connections allowed in your connection class");
265 >      exit_client(source_p, "No more connections allowed in your connection class");
266        break;
267  
268      case NOT_AUTHORIZED:
269        ++ServerStats.is_ref;
270        /* jdc - lists server name & port connections are on */
271        /*       a purely cosmetical change */
272 <      sendto_realops_flags(UMODE_UNAUTH, L_ALL,
273 <                           "Unauthorized client connection from %s [%s] on [%s/%u].",
274 <                           get_client_name(source_p, SHOW_IP),
275 <                           source_p->sockhost,
276 <                           source_p->localClient->listener->name,
277 <                           source_p->localClient->listener->port);
272 >      sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
273 >                           "Unauthorized client connection from %s [%s] on [%s/%u].",
274 >                           get_client_name(source_p, SHOW_IP),
275 >                           source_p->sockhost,
276 >                           source_p->localClient->listener->name,
277 >                           source_p->localClient->listener->port);
278        ilog(LOG_TYPE_IRCD,
279 <          "Unauthorized client connection from %s on [%s/%u].",
280 <          get_client_name(source_p, SHOW_IP),
281 <          source_p->localClient->listener->name,
282 <          source_p->localClient->listener->port);
283 <
284 <      /* XXX It is prolematical whether it is better to use the
861 <       * capture reject code here or rely on the connecting too fast code.
862 <       * - Dianora
863 <       */
864 <      if (REJECT_HOLD_TIME > 0)
865 <      {
866 <        sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
867 <                   me.name, source_p->name);
868 <        source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
869 <        SetCaptured(source_p);
870 <      }
871 <      else
872 <        exit_client(source_p, &me, "You are not authorized to use this server");
279 >           "Unauthorized client connection from %s on [%s/%u].",
280 >           get_client_name(source_p, SHOW_IP),
281 >           source_p->localClient->listener->name,
282 >           source_p->localClient->listener->port);
283 >
284 >      exit_client(source_p, "You are not authorized to use this server");
285        break;
286  
287     case BANNED_CLIENT:
288 <     /*
877 <      * Don't exit them immediately, play with them a bit.
878 <      * - Dianora
879 <      */
880 <     if (REJECT_HOLD_TIME > 0)
881 <     {
882 <       source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
883 <       SetCaptured(source_p);
884 <     }
885 <     else
886 <       exit_client(source_p, &me, "Banned");
288 >     exit_client(source_p, "Banned");
289       ++ServerStats.is_ref;
290       break;
291  
# Line 892 | Line 294 | check_client(va_list args)
294       break;
295    }
296  
297 <  return (i < 0 ? NULL : source_p);
297 >  return (i < 0 ? 0 : 1);
298   }
299  
300   /* verify_access()
301   *
302   * inputs       - pointer to client to verify
901 *              - pointer to proposed username
303   * output       - 0 if success -'ve if not
304   * side effect  - find the first (best) I line to attach.
305   */
306   static int
307 < verify_access(struct Client *client_p, const char *username)
307 > verify_access(struct Client *client_p)
308   {
309 <  struct AccessItem *aconf = NULL, *rkconf = NULL;
310 <  struct ConfItem *conf = NULL;
910 <  char non_ident[USERLEN + 1] = { '~', '\0' };
911 <  const char *uhi[3];
309 >  struct MaskItem *conf = NULL;
310 >  char non_ident[USERLEN + 1] = "~";
311  
312    if (IsGotId(client_p))
313    {
314 <    aconf = find_address_conf(client_p->host, client_p->username,
315 <                             &client_p->localClient->ip,
316 <                             client_p->localClient->aftype,
314 >    conf = find_address_conf(client_p->host, client_p->username,
315 >                             &client_p->localClient->ip,
316 >                             client_p->localClient->aftype,
317                               client_p->localClient->passwd);
318    }
319    else
320    {
321 <    strlcpy(non_ident+1, username, sizeof(non_ident)-1);
322 <    aconf = find_address_conf(client_p->host,non_ident,
323 <                             &client_p->localClient->ip,
324 <                             client_p->localClient->aftype,
325 <                             client_p->localClient->passwd);
321 >    strlcpy(non_ident + 1, client_p->username, sizeof(non_ident) - 1);
322 >    conf = find_address_conf(client_p->host,non_ident,
323 >                             &client_p->localClient->ip,
324 >                             client_p->localClient->aftype,
325 >                             client_p->localClient->passwd);
326    }
327  
328 <  uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
930 <  uhi[1] = client_p->host;
931 <  uhi[2] = client_p->sockhost;
932 <
933 <  rkconf = find_regexp_kline(uhi);
934 <
935 <  if (aconf != NULL)
328 >  if (conf)
329    {
330 <    if (IsConfClient(aconf) && !rkconf)
330 >    if (IsConfClient(conf))
331      {
332 <      conf = unmap_conf_item(aconf);
940 <
941 <      if (IsConfRedir(aconf))
332 >      if (IsConfRedir(conf))
333        {
334 <        sendto_one(client_p, form_str(RPL_REDIR),
335 <                   me.name, client_p->name,
336 <                   conf->name ? conf->name : "",
337 <                   aconf->port);
947 <        return(NOT_AUTHORIZED);
334 >        sendto_one_numeric(client_p, &me, RPL_REDIR,
335 >                           conf->name ? conf->name : "",
336 >                           conf->port);
337 >        return NOT_AUTHORIZED;
338        }
339  
340 <      if (IsConfDoIdentd(aconf))
341 <        SetNeedId(client_p);
340 >      if (IsConfDoIdentd(conf))
341 >        SetNeedId(client_p);
342  
343        /* Thanks for spoof idea amm */
344 <      if (IsConfDoSpoofIp(aconf))
344 >      if (IsConfDoSpoofIp(conf))
345        {
346 <        conf = unmap_conf_item(aconf);
347 <
348 <        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
959 <          sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
346 >        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(conf))
347 >          sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
348 >                               "%s spoofing: %s as %s",
349                                 client_p->name, client_p->host, conf->name);
350          strlcpy(client_p->host, conf->name, sizeof(client_p->host));
351 <        SetIPSpoof(client_p);
351 >        AddFlag(client_p, FLAGS_IP_SPOOFING | FLAGS_AUTH_SPOOF);
352        }
353  
354 <      return(attach_iline(client_p, conf));
354 >      return attach_iline(client_p, conf);
355      }
356 <    else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
356 >    else if (IsConfKill(conf) || (ConfigFileEntry.glines && IsConfGline(conf)))
357      {
358 <      /* XXX */
359 <      aconf = rkconf ? rkconf : aconf;
360 <      if (IsConfGline(aconf))
361 <        sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
973 <                   client_p->name);
974 <      if (ConfigFileEntry.kline_with_reason)
975 <        sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
976 <                  me.name, client_p->name, aconf->reason);
977 <      return(BANNED_CLIENT);
358 >      if (IsConfGline(conf))
359 >        sendto_one_notice(client_p, &me, ":*** G-lined");
360 >      sendto_one_notice(client_p, &me, ":*** Banned: %s", conf->reason);
361 >      return BANNED_CLIENT;
362      }
363    }
364  
365 <  return(NOT_AUTHORIZED);
365 >  return NOT_AUTHORIZED;
366   }
367  
368   /* attach_iline()
# Line 989 | Line 373 | verify_access(struct Client *client_p, c
373   * side effects - do actual attach
374   */
375   static int
376 < attach_iline(struct Client *client_p, struct ConfItem *conf)
376 > attach_iline(struct Client *client_p, struct MaskItem *conf)
377   {
378 <  struct AccessItem *aconf;
995 <  struct ClassItem *aclass;
378 >  struct ClassItem *class = NULL;
379    struct ip_entry *ip_found;
380    int a_limit_reached = 0;
381 <  int local = 0, global = 0, ident = 0;
381 >  unsigned int local = 0, global = 0, ident = 0;
382 >
383 >  assert(conf->class);
384  
385    ip_found = find_or_add_ip(&client_p->localClient->ip);
386    ip_found->count++;
387    SetIpHash(client_p);
388  
389 <  aconf = map_to_conf(conf);
1005 <  if (aconf->class_ptr == NULL)
1006 <    return NOT_AUTHORIZED;  /* If class is missing, this is best */
1007 <
1008 <  aclass = map_to_conf(aconf->class_ptr);
389 >  class = conf->class;
390  
391    count_user_host(client_p->username, client_p->host,
392                    &global, &local, &ident);
# Line 1014 | Line 395 | attach_iline(struct Client *client_p, st
395     * setting a_limit_reached if any limit is reached.
396     * - Dianora
397     */
398 <  if (aclass->max_total != 0 && aclass->curr_user_count >= aclass->max_total)
398 >  if (class->max_total && class->ref_count >= class->max_total)
399      a_limit_reached = 1;
400 <  else if (aclass->max_perip != 0 && ip_found->count > aclass->max_perip)
400 >  else if (class->max_perip && ip_found->count > class->max_perip)
401      a_limit_reached = 1;
402 <  else if (aclass->max_local != 0 && local >= aclass->max_local)
402 >  else if (class->max_local && local >= class->max_local)
403      a_limit_reached = 1;
404 <  else if (aclass->max_global != 0 && global >= aclass->max_global)
404 >  else if (class->max_global && global >= class->max_global)
405      a_limit_reached = 1;
406 <  else if (aclass->max_ident != 0 && ident >= aclass->max_ident &&
406 >  else if (class->max_ident && ident >= class->max_ident &&
407             client_p->username[0] != '~')
408      a_limit_reached = 1;
409  
410    if (a_limit_reached)
411    {
412 <    if (!IsConfExemptLimits(aconf))
412 >    if (!IsConfExemptLimits(conf))
413        return TOO_MANY;   /* Already at maximum allowed */
414  
415 <    sendto_one(client_p,
416 <               ":%s NOTICE %s :*** Your connection class is full, "
1036 <               "but you have exceed_limit = yes;", me.name, client_p->name);
415 >    sendto_one_notice(client_p, &me, ":*** Your connection class is full, "
416 >                      "but you have exceed_limit = yes;");
417    }
418  
419    return attach_conf(client_p, conf);
# Line 1049 | Line 429 | attach_iline(struct Client *client_p, st
429   void
430   init_ip_hash_table(void)
431   {
432 <  ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
1053 <    2 * hard_fdlimit);
432 >  ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
433    memset(ip_hash_table, 0, sizeof(ip_hash_table));
434   }
435  
# Line 1099 | Line 478 | find_or_add_ip(struct irc_ssaddr *ip_in)
478    if (ip_entries_count >= 2 * hard_fdlimit)
479      garbage_collect_ip_entries();
480  
481 <  newptr = BlockHeapAlloc(ip_entry_heap);
481 >  newptr = mp_pool_get(ip_entry_pool);
482 >
483    ip_entries_count++;
484    memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
485  
# Line 1150 | Line 530 | remove_one_ip(struct irc_ssaddr *ip_in)
530      if (ptr->count > 0)
531        ptr->count--;
532      if (ptr->count == 0 &&
533 <        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
533 >        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
534      {
535        if (last_ptr != NULL)
536 <        last_ptr->next = ptr->next;
536 >        last_ptr->next = ptr->next;
537        else
538 <        ip_hash_table[hash_index] = ptr->next;
538 >        ip_hash_table[hash_index] = ptr->next;
539  
540 <      BlockHeapFree(ip_entry_heap, ptr);
540 >      mp_pool_release(ptr);
541        ip_entries_count--;
542        return;
543      }
# Line 1192 | Line 572 | hash_ip(struct irc_ssaddr *addr)
572      uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
573  
574      hash  = ip[0] ^ ip[3];
575 <    hash ^= hash >> 16;  
576 <    hash ^= hash >> 8;  
575 >    hash ^= hash >> 16;
576 >    hash ^= hash >> 8;
577      hash  = hash & (IP_HASH_SIZE - 1);
578      return hash;
579    }
# Line 1204 | Line 584 | hash_ip(struct irc_ssaddr *addr)
584  
585   /* count_ip_hash()
586   *
587 < * inputs        - pointer to counter of number of ips hashed
587 > * inputs        - pointer to counter of number of ips hashed
588   *               - pointer to memory used for ip hash
589   * output        - returned via pointers input
590   * side effects  - NONE
# Line 1216 | Line 596 | void
596   count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
597   {
598    struct ip_entry *ptr;
1219  int i;
599  
600    *number_ips_stored = 0;
601    *mem_ips_stored    = 0;
602  
603 <  for (i = 0; i < IP_HASH_SIZE; i++)
603 >  for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
604    {
605      for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
606      {
# Line 1243 | Line 622 | garbage_collect_ip_entries(void)
622    struct ip_entry *ptr;
623    struct ip_entry *last_ptr;
624    struct ip_entry *next_ptr;
1246  int i;
625  
626 <  for (i = 0; i < IP_HASH_SIZE; i++)
626 >  for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
627    {
628      last_ptr = NULL;
629  
# Line 1260 | Line 638 | garbage_collect_ip_entries(void)
638            last_ptr->next = ptr->next;
639          else
640            ip_hash_table[i] = ptr->next;
641 <        BlockHeapFree(ip_entry_heap, ptr);
641 >        mp_pool_release(ptr);
642          ip_entries_count--;
643        }
644        else
# Line 1277 | Line 655 | garbage_collect_ip_entries(void)
655   * side effects - Disassociate configuration from the client.
656   *                Also removes a class from the list if marked for deleting.
657   */
658 < int
659 < detach_conf(struct Client *client_p, ConfType type)
658 > void
659 > detach_conf(struct Client *client_p, enum maskitem_type type)
660   {
661 <  dlink_node *ptr, *next_ptr;
1284 <  struct ConfItem *conf;
1285 <  struct ClassItem *aclass;
1286 <  struct AccessItem *aconf;
1287 <  struct ConfItem *aclass_conf;
1288 <  struct MatchItem *match_item;
661 >  dlink_node *ptr = NULL, *ptr_next = NULL;
662  
663 <  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
663 >  DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->localClient->confs.head)
664    {
665 <    conf = ptr->data;
1293 <
1294 <    if (type == CONF_TYPE || conf->type == type)
1295 <    {
1296 <      dlinkDelete(ptr, &client_p->localClient->confs);
1297 <      free_dlink_node(ptr);
1298 <
1299 <      switch (conf->type)
1300 <      {
1301 <      case CLIENT_TYPE:
1302 <      case OPER_TYPE:
1303 <      case SERVER_TYPE:
1304 <        aconf = map_to_conf(conf);
1305 <
1306 <        assert(aconf->clients > 0);
665 >    struct MaskItem *conf = ptr->data;
666  
667 <        if ((aclass_conf = aconf->class_ptr) != NULL)
668 <        {
669 <          aclass = map_to_conf(aclass_conf);
1311 <
1312 <          assert(aclass->curr_user_count > 0);
1313 <
1314 <          if (conf->type == CLIENT_TYPE)
1315 <            remove_from_cidr_check(&client_p->localClient->ip, aclass);
1316 <          if (--aclass->curr_user_count == 0 && aclass->active == 0)
1317 <            delete_conf_item(aclass_conf);
1318 <        }
667 >    assert(conf->type & (CONF_CLIENT | CONF_OPER | CONF_SERVER));
668 >    assert(conf->ref_count > 0);
669 >    assert(conf->class->ref_count > 0);
670  
671 <        if (--aconf->clients == 0 && IsConfIllegal(aconf))
672 <          delete_conf_item(conf);
671 >    if (!(conf->type & type))
672 >      continue;
673  
674 <        break;
674 >    dlinkDelete(ptr, &client_p->localClient->confs);
675 >    free_dlink_node(ptr);
676  
677 <      case LEAF_TYPE:
678 <      case HUB_TYPE:
1327 <        match_item = map_to_conf(conf);
1328 <        if (match_item->ref_count == 0 && match_item->illegal)
1329 <          delete_conf_item(conf);
1330 <        break;
1331 <      default:
1332 <        break;
1333 <      }
677 >    if (conf->type == CONF_CLIENT)
678 >      remove_from_cidr_check(&client_p->localClient->ip, conf->class);
679  
680 <      if (type != CONF_TYPE)
681 <        return 0;
680 >    if (--conf->class->ref_count == 0 && conf->class->active == 0)
681 >    {
682 >      class_free(conf->class);
683 >      conf->class = NULL;
684      }
1338  }
685  
686 <  return -1;
686 >    if (--conf->ref_count == 0 && conf->active == 0)
687 >      conf_free(conf);
688 >  }
689   }
690  
691   /* attach_conf()
# Line 1351 | Line 699 | detach_conf(struct Client *client_p, Con
699   *                attachment if there was an old one...
700   */
701   int
702 < attach_conf(struct Client *client_p, struct ConfItem *conf)
702 > attach_conf(struct Client *client_p, struct MaskItem *conf)
703   {
704 <  if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
704 >  if (dlinkFind(&client_p->localClient->confs, conf))
705      return 1;
706  
707 <  if (conf->type == CLIENT_TYPE ||
708 <      conf->type == SERVER_TYPE ||
709 <      conf->type == OPER_TYPE)
710 <  {
1363 <    struct AccessItem *aconf = map_to_conf(conf);
1364 <    struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1365 <
1366 <    if (IsConfIllegal(aconf))
1367 <      return NOT_AUTHORIZED;
1368 <
1369 <    if (conf->type == CLIENT_TYPE)
1370 <      if (cidr_limit_reached(IsConfExemptLimits(aconf),
1371 <                             &client_p->localClient->ip, aclass))
1372 <        return TOO_MANY;    /* Already at maximum allowed */
707 >  if (conf->type == CONF_CLIENT)
708 >    if (cidr_limit_reached(IsConfExemptLimits(conf),
709 >                           &client_p->localClient->ip, conf->class))
710 >      return TOO_MANY;    /* Already at maximum allowed */
711  
712 <    aclass->curr_user_count++;
713 <    aconf->clients++;
1376 <  }
1377 <  else if (conf->type == HUB_TYPE || conf->type == LEAF_TYPE)
1378 <  {
1379 <    struct MatchItem *match_item = map_to_conf(conf);
1380 <    match_item->ref_count++;
1381 <  }
712 >  conf->class->ref_count++;
713 >  conf->ref_count++;
714  
715    dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
716  
# Line 1398 | Line 730 | attach_connect_block(struct Client *clie
730                       const char *host)
731   {
732    dlink_node *ptr;
733 <  struct ConfItem *conf;
1402 <  struct AccessItem *aconf;
733 >  struct MaskItem *conf = NULL;
734  
735    assert(client_p != NULL);
736    assert(host != NULL);
# Line 1410 | Line 741 | attach_connect_block(struct Client *clie
741    DLINK_FOREACH(ptr, server_items.head)
742    {
743      conf = ptr->data;
1413    aconf = map_to_conf(conf);
744  
745 <    if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
745 >    if (match(conf->name, name) || match(conf->host, host))
746        continue;
747  
748      attach_conf(client_p, conf);
# Line 1422 | Line 752 | attach_connect_block(struct Client *clie
752    return 0;
753   }
754  
1425 /* find_conf_exact()
1426 *
1427 * inputs       - type of ConfItem
1428 *              - pointer to name to find
1429 *              - pointer to username to find
1430 *              - pointer to host to find
1431 * output       - NULL or pointer to conf found
1432 * side effects - find a conf entry which matches the hostname
1433 *                and has the same name.
1434 */
1435 struct ConfItem *
1436 find_conf_exact(ConfType type, const char *name, const char *user,
1437                const char *host)
1438 {
1439  dlink_node *ptr;
1440  dlink_list *list_p;
1441  struct ConfItem *conf = NULL;
1442  struct AccessItem *aconf;
1443
1444  /* Only valid for OPER_TYPE and ...? */
1445  list_p = map_to_list(type);
1446
1447  DLINK_FOREACH(ptr, (*list_p).head)
1448  {
1449    conf = ptr->data;
1450
1451    if (conf->name == NULL)
1452      continue;
1453    aconf = map_to_conf(conf);
1454    if (aconf->host == NULL)
1455      continue;
1456    if (irccmp(conf->name, name) != 0)
1457      continue;
1458
1459    /*
1460    ** Accept if the *real* hostname (usually sockethost)
1461    ** socket host) matches *either* host or name field
1462    ** of the configuration.
1463    */
1464    if (!match(aconf->host, host) || !match(aconf->user, user))
1465      continue;
1466    if (type == OPER_TYPE)
1467    {
1468      struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1469
1470      if (aconf->clients >= aclass->max_total)
1471        continue;
1472    }
1473
1474    return conf;
1475  }
1476
1477  return NULL;
1478 }
1479
755   /* find_conf_name()
756   *
757   * inputs       - pointer to conf link list to search
# Line 1486 | Line 761 | find_conf_exact(ConfType type, const cha
761   * side effects - find a conf entry which matches the name
762   *                and has the given mask.
763   */
764 < struct ConfItem *
765 < find_conf_name(dlink_list *list, const char *name, ConfType type)
764 > struct MaskItem *
765 > find_conf_name(dlink_list *list, const char *name, enum maskitem_type type)
766   {
767    dlink_node *ptr;
768 <  struct ConfItem* conf;
768 >  struct MaskItem* conf;
769  
770    DLINK_FOREACH(ptr, list->head)
771    {
772      conf = ptr->data;
773 <    
773 >
774      if (conf->type == type)
775      {
776 <      if (conf->name && (irccmp(conf->name, name) == 0 ||
777 <                         match(conf->name, name)))
776 >      if (conf->name && (!irccmp(conf->name, name) ||
777 >                         !match(conf->name, name)))
778        return conf;
779      }
780    }
# Line 1514 | Line 789 | find_conf_name(dlink_list *list, const c
789   * side effects - none
790   */
791   static dlink_list *
792 < map_to_list(ConfType type)
792 > map_to_list(enum maskitem_type type)
793   {
794    switch(type)
795    {
796 <  case RXLINE_TYPE:
1522 <    return(&rxconf_items);
1523 <    break;
1524 <  case XLINE_TYPE:
796 >  case CONF_XLINE:
797      return(&xconf_items);
798      break;
799 <  case ULINE_TYPE:
799 >  case CONF_ULINE:
800      return(&uconf_items);
801      break;
802 <  case NRESV_TYPE:
802 >  case CONF_NRESV:
803      return(&nresv_items);
804      break;
805 <  case OPER_TYPE:
805 >  case CONF_CRESV:
806 >    return(&cresv_items);
807 >  case CONF_OPER:
808      return(&oconf_items);
809      break;
810 <  case CLASS_TYPE:
1537 <    return(&class_items);
1538 <    break;
1539 <  case SERVER_TYPE:
810 >  case CONF_SERVER:
811      return(&server_items);
812      break;
813 <  case SERVICE_TYPE:
813 >  case CONF_SERVICE:
814      return(&service_items);
815      break;
816 <  case CLUSTER_TYPE:
816 >  case CONF_CLUSTER:
817      return(&cluster_items);
818      break;
1548  case CONF_TYPE:
1549  case GLINE_TYPE:
1550  case KLINE_TYPE:
1551  case DLINE_TYPE:
1552  case CRESV_TYPE:
819    default:
820      return NULL;
821    }
# Line 1561 | Line 827 | map_to_list(ConfType type)
827   *              - pointer to name string to find
828   *              - pointer to user
829   *              - pointer to host
830 < *              - optional action to match on as well
831 < * output       - NULL or pointer to found struct MatchItem
830 > *              - optional flags to match on as well
831 > * output       - NULL or pointer to found struct MaskItem
832   * side effects - looks for a match on name field
833   */
834 < struct ConfItem *
835 < find_matching_name_conf(ConfType type, const char *name, const char *user,
836 <                        const char *host, int action)
834 > struct MaskItem *
835 > find_matching_name_conf(enum maskitem_type type, const char *name, const char *user,
836 >                        const char *host, unsigned int flags)
837   {
838    dlink_node *ptr=NULL;
839 <  struct ConfItem *conf=NULL;
1574 <  struct AccessItem *aconf=NULL;
1575 <  struct MatchItem *match_item=NULL;
839 >  struct MaskItem *conf=NULL;
840    dlink_list *list_p = map_to_list(type);
841  
842    switch (type)
843    {
844 < #ifdef HAVE_LIBPCRE
1581 <  case RXLINE_TYPE:
1582 <      DLINK_FOREACH(ptr, list_p->head)
1583 <      {
1584 <        conf = ptr->data;
1585 <        assert(conf->regexpname);
1586 <
1587 <        if (!ircd_pcre_exec(conf->regexpname, name))
1588 <          return conf;
1589 <      }
1590 <      break;
1591 < #endif
1592 <  case SERVICE_TYPE:
844 >  case CONF_SERVICE:
845      DLINK_FOREACH(ptr, list_p->head)
846      {
847        conf = ptr->data;
# Line 1601 | Line 853 | find_matching_name_conf(ConfType type, c
853      }
854      break;
855  
856 <  case XLINE_TYPE:
857 <  case ULINE_TYPE:
858 <  case NRESV_TYPE:
856 >  case CONF_XLINE:
857 >  case CONF_ULINE:
858 >  case CONF_NRESV:
859 >  case CONF_CRESV:
860      DLINK_FOREACH(ptr, list_p->head)
861      {
862        conf = ptr->data;
863  
1611      match_item = map_to_conf(conf);
864        if (EmptyString(conf->name))
865 <        continue;
866 <      if ((name != NULL) && match_esc(conf->name, name))
865 >        continue;
866 >      if ((name != NULL) && !match(conf->name, name))
867        {
868 <        if ((user == NULL && (host == NULL)))
869 <          return conf;
870 <        if ((match_item->action & action) != action)
868 >        if ((user == NULL && (host == NULL)))
869 >          return conf;
870 >        if ((conf->flags & flags) != flags)
871            continue;
872 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
873 <          return conf;
874 <        if (match(match_item->user, user) && match(match_item->host, host))
875 <          return conf;
872 >        if (EmptyString(conf->user) || EmptyString(conf->host))
873 >          return conf;
874 >        if (!match(conf->user, user) && !match(conf->host, host))
875 >          return conf;
876        }
877      }
878        break;
879  
880 <  case SERVER_TYPE:
880 >  case CONF_SERVER:
881      DLINK_FOREACH(ptr, list_p->head)
882      {
883        conf = ptr->data;
1632      aconf = map_to_conf(conf);
884  
885 <      if ((name != NULL) && match_esc(name, conf->name))
885 >      if ((name != NULL) && !match(name, conf->name))
886          return conf;
887 <      else if ((host != NULL) && match_esc(host, aconf->host))
887 >      else if ((host != NULL) && !match(host, conf->host))
888          return conf;
889      }
890      break;
891 <  
891 >
892    default:
893      break;
894    }
# Line 1650 | Line 901 | find_matching_name_conf(ConfType type, c
901   *              - pointer to name string to find
902   *              - pointer to user
903   *              - pointer to host
904 < * output       - NULL or pointer to found struct MatchItem
904 > * output       - NULL or pointer to found struct MaskItem
905   * side effects - looks for an exact match on name field
906   */
907 < struct ConfItem *
908 < find_exact_name_conf(ConfType type, const struct Client *who, const char *name,
907 > struct MaskItem *
908 > find_exact_name_conf(enum maskitem_type type, const struct Client *who, const char *name,
909                       const char *user, const char *host)
910   {
911    dlink_node *ptr = NULL;
912 <  struct AccessItem *aconf;
913 <  struct ConfItem *conf;
1663 <  struct MatchItem *match_item;
1664 <  dlink_list *list_p;
1665 <
1666 <  list_p = map_to_list(type);
912 >  struct MaskItem *conf;
913 >  dlink_list *list_p = map_to_list(type);
914  
915    switch(type)
916    {
917 <  case RXLINE_TYPE:
918 <  case XLINE_TYPE:
919 <  case ULINE_TYPE:
920 <  case NRESV_TYPE:
917 >  case CONF_XLINE:
918 >  case CONF_ULINE:
919 >  case CONF_NRESV:
920 >  case CONF_CRESV:
921  
922      DLINK_FOREACH(ptr, list_p->head)
923      {
924        conf = ptr->data;
925 <      match_item = (struct MatchItem *)map_to_conf(conf);
925 >
926        if (EmptyString(conf->name))
927 <        continue;
928 <    
927 >        continue;
928 >
929        if (irccmp(conf->name, name) == 0)
930        {
931 <        if ((user == NULL && (host == NULL)))
932 <          return (conf);
933 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
934 <          return (conf);
935 <        if (match(match_item->user, user) && match(match_item->host, host))
936 <          return (conf);
931 >        if ((user == NULL && (host == NULL)))
932 >          return conf;
933 >        if (EmptyString(conf->user) || EmptyString(conf->host))
934 >          return conf;
935 >        if (!match(conf->user, user) && !match(conf->host, host))
936 >          return conf;
937        }
938      }
939      break;
940  
941 <  case OPER_TYPE:
941 >  case CONF_OPER:
942      DLINK_FOREACH(ptr, list_p->head)
943      {
944        conf = ptr->data;
1698      aconf = map_to_conf(conf);
945  
946        if (EmptyString(conf->name))
947          continue;
# Line 1704 | Line 950 | find_exact_name_conf(ConfType type, cons
950        {
951          if (!who)
952            return conf;
953 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
954 <          return conf;
955 <        if (match(aconf->user, who->username))
953 >        if (EmptyString(conf->user) || EmptyString(conf->host))
954 >          return NULL;
955 >        if (!match(conf->user, who->username))
956          {
957 <          switch (aconf->type)
957 >          switch (conf->htype)
958            {
959              case HM_HOST:
960 <              if (match(aconf->host, who->host) || match(aconf->host, who->sockhost))
961 <                return conf;
960 >              if (!match(conf->host, who->host) || !match(conf->host, who->sockhost))
961 >                if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
962 >                  return conf;
963                break;
964              case HM_IPV4:
965                if (who->localClient->aftype == AF_INET)
966 <                if (match_ipv4(&who->localClient->ip, &aconf->ipnum, aconf->bits))
967 <                  return conf;
966 >                if (match_ipv4(&who->localClient->ip, &conf->addr, conf->bits))
967 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
968 >                    return conf;
969                break;
970   #ifdef IPV6
971              case HM_IPV6:
972                if (who->localClient->aftype == AF_INET6)
973 <                if (match_ipv6(&who->localClient->ip, &aconf->ipnum, aconf->bits))
974 <                  return conf;
973 >                if (match_ipv6(&who->localClient->ip, &conf->addr, conf->bits))
974 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
975 >                    return conf;
976                break;
977   #endif
978              default:
# Line 1735 | Line 984 | find_exact_name_conf(ConfType type, cons
984  
985      break;
986  
987 <  case SERVER_TYPE:
987 >  case CONF_SERVER:
988      DLINK_FOREACH(ptr, list_p->head)
989      {
990        conf = ptr->data;
991 <      aconf = (struct AccessItem *)map_to_conf(conf);
991 >
992        if (EmptyString(conf->name))
993 <        continue;
994 <    
993 >        continue;
994 >
995        if (name == NULL)
996        {
997 <        if (EmptyString(aconf->host))
998 <          continue;
999 <        if (irccmp(aconf->host, host) == 0)
1000 <          return(conf);
997 >        if (EmptyString(conf->host))
998 >          continue;
999 >        if (irccmp(conf->host, host) == 0)
1000 >          return conf;
1001        }
1002        else if (irccmp(conf->name, name) == 0)
1003 <      {
1755 <          return (conf);
1756 <      }
1003 >        return conf;
1004      }
1758    break;
1005  
1760  case CLASS_TYPE:
1761    DLINK_FOREACH(ptr, list_p->head)
1762    {
1763      conf = ptr->data;
1764      if (EmptyString(conf->name))
1765        continue;
1766    
1767      if (irccmp(conf->name, name) == 0)
1768        return (conf);
1769    }
1006      break;
1007  
1008    default:
1009      break;
1010    }
1011 <  return(NULL);
1011 >
1012 >  return NULL;
1013   }
1014  
1015   /* rehash()
# Line 1784 | Line 1021 | find_exact_name_conf(ConfType type, cons
1021   int
1022   rehash(int sig)
1023   {
1024 <  if (sig != 0)
1025 <    sendto_realops_flags(UMODE_ALL, L_ALL,
1026 <                         "Got signal SIGHUP, reloading ircd.conf file");
1024 >  if (sig)
1025 >    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1026 >                         "Got signal SIGHUP, reloading configuration file(s)");
1027  
1028    restart_resolver();
1029  
# Line 1797 | Line 1034 | rehash(int sig)
1034  
1035    read_conf_files(0);
1036  
1037 <  if (ServerInfo.description != NULL)
1037 >  if (ServerInfo.description)
1038      strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1039  
1040    load_conf_modules();
1041 +  check_conf_klines();
1042  
1043 <  flush_deleted_I_P();
1806 <
1807 <  rehashed_klines = 1;
1808 < /* XXX */
1809 <  if (ConfigLoggingEntry.use_logging)
1810 <    log_close_all();
1811 <
1812 <  return(0);
1043 >  return 0;
1044   }
1045  
1046   /* set_default_conf()
# Line 1827 | Line 1058 | set_default_conf(void)
1058    /* verify init_class() ran, this should be an unnecessary check
1059     * but its not much work.
1060     */
1061 <  assert(class_default == (struct ConfItem *) class_items.tail->data);
1061 >  assert(class_default == class_get_list()->tail->data);
1062  
1063   #ifdef HAVE_LIBCRYPTO
1064 +  ServerInfo.message_digest_algorithm = EVP_sha256();
1065    ServerInfo.rsa_private_key = NULL;
1066    ServerInfo.rsa_private_key_file = NULL;
1067   #endif
# Line 1837 | Line 1069 | set_default_conf(void)
1069    /* ServerInfo.name is not rehashable */
1070    /* ServerInfo.name = ServerInfo.name; */
1071    ServerInfo.description = NULL;
1072 <  DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1073 <  DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1072 >  ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1073 >  ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1074  
1075    memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1076    ServerInfo.specific_ipv4_vhost = 0;
# Line 1846 | Line 1078 | set_default_conf(void)
1078    ServerInfo.specific_ipv6_vhost = 0;
1079  
1080    ServerInfo.max_clients = MAXCLIENTS_MAX;
1081 +  ServerInfo.max_nick_length = 9;
1082 +  ServerInfo.max_topic_length = 80;
1083  
1084    ServerInfo.hub = 0;
1085    ServerInfo.dns_host.sin_addr.s_addr = 0;
# Line 1854 | Line 1088 | set_default_conf(void)
1088    AdminInfo.email = NULL;
1089    AdminInfo.description = NULL;
1090  
1091 <  log_close_all();
1091 >  log_del_all();
1092  
1093    ConfigLoggingEntry.use_logging = 1;
1094  
1095    ConfigChannel.disable_fake_channels = 0;
1096 <  ConfigChannel.restrict_channels = 0;
1097 <  ConfigChannel.disable_local_channels = 0;
1098 <  ConfigChannel.use_invex = 1;
1099 <  ConfigChannel.use_except = 1;
1866 <  ConfigChannel.use_knock = 1;
1867 <  ConfigChannel.knock_delay = 300;
1096 >  ConfigChannel.invite_client_count = 10;
1097 >  ConfigChannel.invite_client_time = 300;
1098 >  ConfigChannel.knock_client_count = 1;
1099 >  ConfigChannel.knock_client_time = 300;
1100    ConfigChannel.knock_delay_channel = 60;
1101 <  ConfigChannel.max_chans_per_user = 15;
1870 <  ConfigChannel.quiet_on_ban = 1;
1101 >  ConfigChannel.max_channels = 25;
1102    ConfigChannel.max_bans = 25;
1103    ConfigChannel.default_split_user_count = 0;
1104    ConfigChannel.default_split_server_count = 0;
1105    ConfigChannel.no_join_on_split = 0;
1106    ConfigChannel.no_create_on_split = 0;
1876  ConfigChannel.burst_topicwho = 1;
1107  
1108    ConfigServerHide.flatten_links = 0;
1109    ConfigServerHide.links_delay = 300;
1110    ConfigServerHide.hidden = 0;
1881  ConfigServerHide.disable_hidden = 0;
1111    ConfigServerHide.hide_servers = 0;
1112 <  DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1112 >  ConfigServerHide.hide_services = 0;
1113 >  ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
1114    ConfigServerHide.hide_server_ips = 0;
1115 +  ConfigServerHide.disable_remote_commands = 0;
1116  
1117 <  
1887 <  DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1117 >  ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1118    ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1119 +  ConfigFileEntry.cycle_on_host_change = 1;
1120 +  ConfigFileEntry.glines = 0;
1121 +  ConfigFileEntry.gline_time = 12 * 3600;
1122 +  ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
1123    ConfigFileEntry.gline_min_cidr = 16;
1124    ConfigFileEntry.gline_min_cidr6 = 48;
1125    ConfigFileEntry.invisible_on_connect = 1;
1892  ConfigFileEntry.burst_away = 0;
1893  ConfigFileEntry.use_whois_actually = 1;
1126    ConfigFileEntry.tkline_expire_notices = 1;
1127    ConfigFileEntry.hide_spoof_ips = 1;
1128    ConfigFileEntry.ignore_bogus_ts = 0;
1129    ConfigFileEntry.disable_auth = 0;
1898  ConfigFileEntry.disable_remote = 0;
1130    ConfigFileEntry.kill_chase_time_limit = 90;
1131    ConfigFileEntry.default_floodcount = 8;
1132    ConfigFileEntry.failed_oper_notice = 1;
# Line 1909 | Line 1140 | set_default_conf(void)
1140    ConfigFileEntry.anti_spam_exit_message_time = 0;
1141    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1142    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1143 <  ConfigFileEntry.kline_with_reason = 1;
1144 <  ConfigFileEntry.kline_reason = NULL;
1914 <  ConfigFileEntry.warn_no_nline = 1;
1143 >  ConfigFileEntry.warn_no_connect_block = 1;
1144 >  ConfigFileEntry.stats_e_disabled = 0;
1145    ConfigFileEntry.stats_o_oper_only = 0;
1146 <  ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
1147 <  ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
1146 >  ConfigFileEntry.stats_k_oper_only = 1;  /* 1 = masked */
1147 >  ConfigFileEntry.stats_i_oper_only = 1;  /* 1 = masked */
1148    ConfigFileEntry.stats_P_oper_only = 0;
1149 +  ConfigFileEntry.stats_u_oper_only = 0;
1150    ConfigFileEntry.caller_id_wait = 60;
1151    ConfigFileEntry.opers_bypass_callerid = 0;
1152    ConfigFileEntry.pace_wait = 10;
# Line 1925 | Line 1156 | set_default_conf(void)
1156    ConfigFileEntry.no_oper_flood = 0;
1157    ConfigFileEntry.true_no_oper_flood = 0;
1158    ConfigFileEntry.oper_pass_resv = 1;
1928  ConfigFileEntry.glines = 0;
1929  ConfigFileEntry.gline_time = 12 * 3600;
1159    ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1931  ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1160    ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1161 <  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1934 <    UMODE_OPERWALL | UMODE_WALLOP;
1161 >  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE | UMODE_WALLOP;
1162    ConfigFileEntry.use_egd = 0;
1163    ConfigFileEntry.egdpool_path = NULL;
1164 <  ConfigFileEntry.throttle_time = 10;
1164 >  ConfigFileEntry.throttle_count = 1;
1165 >  ConfigFileEntry.throttle_time = 1;
1166   }
1167  
1168   static void
# Line 1947 | Line 1175 | validate_conf(void)
1175      ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1176  
1177    if (ServerInfo.network_name == NULL)
1178 <    DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1178 >    ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1179  
1180    if (ServerInfo.network_desc == NULL)
1181 <    DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1181 >    ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1182  
1183    if (ConfigFileEntry.service_name == NULL)
1184 <    DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1957 <
1958 <  if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1959 <      (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1960 <    ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1184 >    ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1185  
1186    ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1187   }
1188  
1189 < /* read_conf()
1189 > /* read_conf()
1190   *
1191   * inputs       - file descriptor pointing to config file to use
1192   * output       - None
# Line 1973 | Line 1197 | read_conf(FILE *file)
1197   {
1198    lineno = 0;
1199  
1200 <  set_default_conf(); /* Set default values prior to conf parsing */
1200 >  set_default_conf();  /* Set default values prior to conf parsing */
1201    conf_parser_ctx.pass = 1;
1202 <  yyparse();          /* pick up the classes first */
1202 >  yyparse();  /* Pick up the classes first */
1203  
1204    rewind(file);
1205  
1206    conf_parser_ctx.pass = 2;
1207 <  yyparse();          /* Load the values from the conf */
1208 <  validate_conf();    /* Check to make sure some values are still okay. */
1209 <                      /* Some global values are also loaded here. */
1210 <  check_class();      /* Make sure classes are valid */
1207 >  yyparse();  /* Load the values from the conf */
1208 >  validate_conf();  /* Check to make sure some values are still okay. */
1209 >                    /* Some global values are also loaded here. */
1210 >  class_delete_marked();  /* Delete unused classes that are marked for deletion */
1211   }
1212  
1213   /* lookup_confhost()
# Line 1991 | Line 1215 | read_conf(FILE *file)
1215   * start DNS lookups of all hostnames in the conf
1216   * line and convert an IP addresses in a.b.c.d number for to IP#s.
1217   */
1218 < static void
1219 < lookup_confhost(struct ConfItem *conf)
1218 > void
1219 > lookup_confhost(struct MaskItem *conf)
1220   {
1997  struct AccessItem *aconf;
1221    struct addrinfo hints, *res;
1222  
1223 <  aconf = map_to_conf(conf);
1224 <
2002 <  if (EmptyString(aconf->host) ||
2003 <      EmptyString(aconf->user))
2004 <  {
2005 <    ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
2006 <         aconf->host, conf->name);
2007 <    return;
2008 <  }
2009 <
2010 <  if (strchr(aconf->host, '*') ||
2011 <      strchr(aconf->host, '?'))
2012 <    return;
2013 <
2014 <  /* Do name lookup now on hostnames given and store the
1223 >  /*
1224 >   * Do name lookup now on hostnames given and store the
1225     * ip numbers in conf structure.
1226     */
1227    memset(&hints, 0, sizeof(hints));
# Line 2022 | Line 1232 | lookup_confhost(struct ConfItem *conf)
1232    /* Get us ready for a bind() and don't bother doing dns lookup */
1233    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1234  
1235 <  if (getaddrinfo(aconf->host, NULL, &hints, &res))
1235 >  if (getaddrinfo(conf->host, NULL, &hints, &res))
1236    {
1237 <    conf_dns_lookup(aconf);
1237 >    conf_dns_lookup(conf);
1238      return;
1239    }
1240  
1241 <  assert(res != NULL);
1241 >  assert(res);
1242 >
1243 >  memcpy(&conf->addr, res->ai_addr, res->ai_addrlen);
1244 >  conf->addr.ss_len = res->ai_addrlen;
1245 >  conf->addr.ss.ss_family = res->ai_family;
1246  
2033  memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
2034  aconf->ipnum.ss_len = res->ai_addrlen;
2035  aconf->ipnum.ss.ss_family = res->ai_family;
1247    freeaddrinfo(res);
1248   }
1249  
# Line 2046 | Line 1257 | lookup_confhost(struct ConfItem *conf)
1257   int
1258   conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1259   {
1260 <  struct ip_entry *ip_found;
1261 <  struct AccessItem *aconf = find_dline_conf(addr, aftype);
1260 >  struct ip_entry *ip_found = NULL;
1261 >  struct MaskItem *conf = find_dline_conf(addr, aftype);
1262  
1263    /* DLINE exempt also gets you out of static limits/pacing... */
1264 <  if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1264 >  if (conf && (conf->type == CONF_EXEMPT))
1265      return 0;
1266  
1267 <  if (aconf != NULL)
1267 >  if (conf)
1268      return BANNED_CLIENT;
1269  
1270    ip_found = find_or_add_ip(addr);
1271  
1272 <  if ((CurrentTime - ip_found->last_attempt) <
2062 <      ConfigFileEntry.throttle_time)
1272 >  if ((CurrentTime - ip_found->last_attempt) < ConfigFileEntry.throttle_time)
1273    {
1274 <    ip_found->last_attempt = CurrentTime;
1275 <    return TOO_FAST;
1274 >    if (ip_found->connection_count >= ConfigFileEntry.throttle_count)
1275 >      return TOO_FAST;
1276 >
1277 >    ++ip_found->connection_count;
1278    }
1279 +  else
1280 +    ip_found->connection_count = 1;
1281  
1282    ip_found->last_attempt = CurrentTime;
1283    return 0;
1284   }
1285  
2072 static struct AccessItem *
2073 find_regexp_kline(const char *uhi[])
2074 {
2075 #ifdef HAVE_LIBPCRE
2076  const dlink_node *ptr = NULL;
2077
2078  DLINK_FOREACH(ptr, rkconf_items.head)
2079  {
2080    struct AccessItem *aptr = map_to_conf(ptr->data);
2081
2082    assert(aptr->regexuser);
2083    assert(aptr->regexhost);
2084
2085    if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2086        (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2087         !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2088      return aptr;
2089  }
2090 #endif
2091  return NULL;
2092 }
2093
2094 /* find_kill()
2095 *
2096 * inputs       - pointer to client structure
2097 * output       - pointer to struct AccessItem if found
2098 * side effects - See if this user is klined already,
2099 *                and if so, return struct AccessItem pointer
2100 */
2101 struct AccessItem *
2102 find_kill(struct Client *client_p)
2103 {
2104  struct AccessItem *aconf = NULL;
2105  const char *uhi[3];
2106
2107  uhi[0] = client_p->username;
2108  uhi[1] = client_p->host;
2109  uhi[2] = client_p->sockhost;
2110
2111  assert(client_p != NULL);
2112
2113  aconf = find_kline_conf(client_p->host, client_p->username,
2114                          &client_p->localClient->ip,
2115                          client_p->localClient->aftype);
2116  if (aconf == NULL)
2117    aconf = find_regexp_kline(uhi);
2118
2119  if (aconf && (aconf->status & CONF_KLINE))
2120    return aconf;
2121
2122  return NULL;
2123 }
2124
2125 struct AccessItem *
2126 find_gline(struct Client *client_p)
2127 {
2128  struct AccessItem *aconf;
2129
2130  assert(client_p != NULL);
2131
2132  aconf = find_gline_conf(client_p->host, client_p->username,
2133                          &client_p->localClient->ip,
2134                          client_p->localClient->aftype);
2135
2136  if (aconf && (aconf->status & CONF_GLINE))
2137    return aconf;
2138
2139  return NULL;
2140 }
2141
2142 /* add_temp_line()
2143 *
2144 * inputs        - pointer to struct ConfItem
2145 * output        - none
2146 * Side effects  - links in given struct ConfItem into
2147 *                 temporary *line link list
2148 */
2149 void
2150 add_temp_line(struct ConfItem *conf)
2151 {
2152  if (conf->type == XLINE_TYPE)
2153  {
2154    conf->flags |= CONF_FLAGS_TEMPORARY;
2155    dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2156  }
2157  else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2158  {
2159    conf->flags |= CONF_FLAGS_TEMPORARY;
2160    dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2161  }
2162 }
2163
1286   /* cleanup_tklines()
1287   *
1288   * inputs       - NONE
# Line 2172 | Line 1294 | void
1294   cleanup_tklines(void *notused)
1295   {
1296    hostmask_expire_temporary();
1297 <  expire_tklines(&temporary_xlines);
1298 <  expire_tklines(&temporary_resv);
1297 >  expire_tklines(&xconf_items);
1298 >  expire_tklines(&nresv_items);
1299 >  expire_tklines(&cresv_items);
1300   }
1301  
1302   /* expire_tklines()
# Line 2185 | Line 1308 | cleanup_tklines(void *notused)
1308   static void
1309   expire_tklines(dlink_list *tklist)
1310   {
1311 <  dlink_node *ptr;
1312 <  dlink_node *next_ptr;
2190 <  struct ConfItem *conf;
2191 <  struct MatchItem *xconf;
2192 <  struct MatchItem *nconf;
2193 <  struct ResvChannel *cconf;
1311 >  dlink_node *ptr = NULL, *ptr_next = NULL;
1312 >  struct MaskItem *conf = NULL;
1313  
1314 <  DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
1314 >  DLINK_FOREACH_SAFE(ptr, ptr_next, tklist->head)
1315    {
1316      conf = ptr->data;
1317  
1318 <    if (conf->type == XLINE_TYPE)
1318 >    if (!conf->until || conf->until > CurrentTime)
1319 >      continue;
1320 >
1321 >    if (conf->type == CONF_XLINE)
1322      {
1323 <      xconf = (struct MatchItem *)map_to_conf(conf);
1324 <      if (xconf->hold <= CurrentTime)
1325 <      {
1326 <        if (ConfigFileEntry.tkline_expire_notices)
2205 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2206 <                               "Temporary X-line for [%s] sexpired", conf->name);
2207 <        dlinkDelete(ptr, tklist);
2208 <        free_dlink_node(ptr);
2209 <        delete_conf_item(conf);
2210 <      }
1323 >      if (ConfigFileEntry.tkline_expire_notices)
1324 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1325 >                               "Temporary X-line for [%s] expired", conf->name);
1326 >      conf_free(conf);
1327      }
1328 <    else if (conf->type == NRESV_TYPE)
1328 >    else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1329      {
1330 <      nconf = (struct MatchItem *)map_to_conf(conf);
1331 <      if (nconf->hold <= CurrentTime)
2216 <      {
2217 <        if (ConfigFileEntry.tkline_expire_notices)
2218 <          sendto_realops_flags(UMODE_ALL, L_ALL,
1330 >      if (ConfigFileEntry.tkline_expire_notices)
1331 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1332                                 "Temporary RESV for [%s] expired", conf->name);
1333 <        dlinkDelete(ptr, tklist);
2221 <        free_dlink_node(ptr);
2222 <        delete_conf_item(conf);
2223 <      }
2224 <    }
2225 <    else if (conf->type == CRESV_TYPE)
2226 <    {
2227 <      cconf = (struct ResvChannel *)map_to_conf(conf);
2228 <      if (cconf->hold <= CurrentTime)
2229 <      {
2230 <        if (ConfigFileEntry.tkline_expire_notices)
2231 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2232 <                               "Temporary RESV for [%s] expired", cconf->name);
2233 <        delete_channel_resv(cconf);
2234 <      }
1333 >      conf_free(conf);
1334      }
1335    }
1336   }
# Line 2244 | Line 1343 | expire_tklines(dlink_list *tklist)
1343   */
1344   static const struct oper_privs
1345   {
1346 <  const unsigned int oprivs;
1346 >  const unsigned int flag;
1347    const unsigned char c;
1348   } flag_list[] = {
1349 <  { OPER_FLAG_ADMIN,       'A' },
1350 <  { OPER_FLAG_REMOTEBAN,   'B' },
1351 <  { OPER_FLAG_DIE,         'D' },
1352 <  { OPER_FLAG_GLINE,       'G' },
1353 <  { OPER_FLAG_REHASH,      'H' },
1354 <  { OPER_FLAG_K,           'K' },
1355 <  { OPER_FLAG_OPERWALL,    'L' },
1356 <  { OPER_FLAG_N,           'N' },
1357 <  { OPER_FLAG_GLOBAL_KILL, 'O' },
1358 <  { OPER_FLAG_REMOTE,      'R' },
1359 <  { OPER_FLAG_OPER_SPY,    'S' },
1360 <  { OPER_FLAG_UNKLINE,     'U' },
1361 <  { OPER_FLAG_X,           'X' },
1349 >  { OPER_FLAG_ADMIN,          'A' },
1350 >  { OPER_FLAG_REMOTEBAN,      'B' },
1351 >  { OPER_FLAG_DIE,            'D' },
1352 >  { OPER_FLAG_GLINE,          'G' },
1353 >  { OPER_FLAG_REHASH,         'H' },
1354 >  { OPER_FLAG_KLINE,          'K' },
1355 >  { OPER_FLAG_KILL,           'N' },
1356 >  { OPER_FLAG_KILL_REMOTE,    'O' },
1357 >  { OPER_FLAG_CONNECT,        'P' },
1358 >  { OPER_FLAG_CONNECT_REMOTE, 'Q' },
1359 >  { OPER_FLAG_SQUIT,          'R' },
1360 >  { OPER_FLAG_SQUIT_REMOTE,   'S' },
1361 >  { OPER_FLAG_UNKLINE,        'U' },
1362 >  { OPER_FLAG_XLINE,          'X' },
1363    { 0, '\0' }
1364   };
1365  
1366   char *
1367   oper_privs_as_string(const unsigned int port)
1368   {
1369 <  static char privs_out[16];
1369 >  static char privs_out[IRCD_BUFSIZE];
1370    char *privs_ptr = privs_out;
2271  unsigned int i = 0;
1371  
1372 <  for (; flag_list[i].oprivs; ++i)
1372 >  for (const struct oper_privs *opriv = flag_list; opriv->flag; ++opriv)
1373    {
1374 <    if (port & flag_list[i].oprivs)
1375 <      *privs_ptr++ = flag_list[i].c;
1374 >    if (port & opriv->flag)
1375 >      *privs_ptr++ = opriv->c;
1376      else
1377 <      *privs_ptr++ = ToLowerTab[flag_list[i].c];
1377 >      *privs_ptr++ = ToLower(opriv->c);
1378    }
1379  
1380    *privs_ptr = '\0';
# Line 2292 | Line 1391 | oper_privs_as_string(const unsigned int
1391   const char *
1392   get_oper_name(const struct Client *client_p)
1393   {
1394 <  dlink_node *cnode = NULL;
1394 >  const dlink_node *cnode = NULL;
1395    /* +5 for !,@,{,} and null */
1396    static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
1397  
# Line 2300 | Line 1399 | get_oper_name(const struct Client *clien
1399    {
1400      if ((cnode = client_p->localClient->confs.head))
1401      {
1402 <      struct ConfItem *conf = cnode->data;
2304 <      const struct AccessItem *aconf = map_to_conf(conf);
1402 >      const struct MaskItem *conf = cnode->data;
1403  
1404 <      if (IsConfOperator(aconf))
1404 >      if (IsConfOperator(conf))
1405        {
1406 <        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1406 >        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1407                   client_p->username, client_p->host, conf->name);
1408 <        return buffer;
1408 >        return buffer;
1409        }
1410      }
1411  
1412 <    /* Probably should assert here for now. If there is an oper out there
1412 >    /* Probably should assert here for now. If there is an oper out there
1413       * with no oper{} conf attached, it would be good for us to know...
1414       */
1415      assert(0); /* Oper without oper conf! */
1416    }
1417  
1418    snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1419 <           client_p->username, client_p->host, client_p->servptr->name);
1419 >           client_p->username, client_p->host, client_p->servptr->name);
1420    return buffer;
1421   }
1422  
# Line 2331 | Line 1429 | get_oper_name(const struct Client *clien
1429   void
1430   read_conf_files(int cold)
1431   {
1432 <  const char *filename;
1433 <  char chanmodes[32];
1434 <  char chanlimit[32];
1432 >  const char *filename = NULL;
1433 >  char chanmodes[IRCD_BUFSIZE] = "";
1434 >  char chanlimit[IRCD_BUFSIZE] = "";
1435  
1436    conf_parser_ctx.boot = cold;
1437 <  filename = get_conf_name(CONF_TYPE);
1437 >  filename = ConfigFileEntry.configfile;
1438  
1439    /* We need to know the initial filename for the yyerror() to report
1440       FIXME: The full path is in conffilenamebuf first time since we
1441               dont know anything else
1442  
1443 <     - Gozem 2002-07-21
1443 >     - Gozem 2002-07-21
1444    */
1445    strlcpy(conffilebuf, filename, sizeof(conffilebuf));
1446  
# Line 2356 | Line 1454 | read_conf_files(int cold)
1454      }
1455      else
1456      {
1457 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1458 <                           "Unable to read configuration file '%s': %s",
1459 <                           filename, strerror(errno));
1457 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1458 >                           "Unable to read configuration file '%s': %s",
1459 >                           filename, strerror(errno));
1460        return;
1461      }
1462    }
# Line 2369 | Line 1467 | read_conf_files(int cold)
1467    read_conf(conf_parser_ctx.conf_file);
1468    fclose(conf_parser_ctx.conf_file);
1469  
1470 +  log_reopen_all();
1471 +
1472 +  add_isupport("NICKLEN", NULL, ServerInfo.max_nick_length);
1473    add_isupport("NETWORK", ServerInfo.network_name, -1);
1474 <  snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
1475 <           ConfigChannel.use_except ? "e" : "",
2375 <           ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
1474 >
1475 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1476    add_isupport("MAXLIST", chanmodes, -1);
1477    add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1478 +  add_isupport("CHANTYPES", "#", -1);
1479  
1480 <  if (ConfigChannel.disable_local_channels)
1481 <    add_isupport("CHANTYPES", "#", -1);
2381 <  else
2382 <    add_isupport("CHANTYPES", "#&", -1);
2383 <
2384 <  snprintf(chanlimit, sizeof(chanlimit), "%s:%d",
2385 <           ConfigChannel.disable_local_channels ? "#" : "#&",
2386 <           ConfigChannel.max_chans_per_user);
1480 >  snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1481 >           ConfigChannel.max_channels);
1482    add_isupport("CHANLIMIT", chanlimit, -1);
1483 <  snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
1484 <           ConfigChannel.use_except ? "e" : "",
1485 <           ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
2391 <  add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2392 <
2393 <  if (ConfigChannel.use_except)
2394 <    add_isupport("EXCEPTS", "e", -1);
2395 <  if (ConfigChannel.use_invex)
2396 <    add_isupport("INVEX", "I", -1);
1483 >  snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,cimnprstMORS");
1484 >  add_isupport("CHANNELLEN", NULL, CHANNELLEN);
1485 >  add_isupport("TOPICLEN", NULL, ServerInfo.max_topic_length);
1486    add_isupport("CHANMODES", chanmodes, -1);
1487  
1488    /*
# Line 2401 | Line 1490 | read_conf_files(int cold)
1490     * on strlen(form_str(RPL_ISUPPORT))
1491     */
1492    rebuild_isupport_message_line();
2404
2405 #ifdef HAVE_LIBPCRE
2406  parse_conf_file(RKLINE_TYPE, cold);
2407  parse_conf_file(RXLINE_TYPE, cold);
2408 #endif
2409  parse_conf_file(KLINE_TYPE, cold);
2410  parse_conf_file(DLINE_TYPE, cold);
2411  parse_conf_file(XLINE_TYPE, cold);
2412  parse_conf_file(NRESV_TYPE, cold);
2413  parse_conf_file(CRESV_TYPE, cold);
2414 }
2415
2416 /* parse_conf_file()
2417 *
2418 * inputs       - type of conf file to parse
2419 * output       - none
2420 * side effects - conf file for givenconf type is opened and read then parsed
2421 */
2422 static void
2423 parse_conf_file(int type, int cold)
2424 {
2425  FILE *file = NULL;
2426  const char *filename = get_conf_name(type);
2427
2428  if ((file = fopen(filename, "r")) == NULL)
2429  {
2430    if (cold)
2431      ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2432           filename, strerror(errno));
2433    else
2434      sendto_realops_flags(UMODE_ALL, L_ALL,
2435                    "Unable to read configuration file '%s': %s",
2436                           filename, strerror(errno));
2437  }
2438  else
2439  {
2440    parse_csv_file(file, type);
2441    fclose(file);
2442  }
1493   }
1494  
1495   /* clear_out_old_conf()
# Line 2452 | Line 1502 | static void
1502   clear_out_old_conf(void)
1503   {
1504    dlink_node *ptr = NULL, *next_ptr = NULL;
1505 <  struct ConfItem *conf;
2456 <  struct AccessItem *aconf;
2457 <  struct ClassItem *cltmp;
2458 <  struct MatchItem *match_item;
1505 >  struct MaskItem *conf;
1506    dlink_list *free_items [] = {
1507 <    &server_items,   &oconf_items,    &hub_items, &leaf_items,
1508 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1509 <     &nresv_items, &cluster_items,  &gdeny_items, &service_items, NULL
1507 >    &server_items,   &oconf_items,
1508 >     &uconf_items,   &xconf_items,
1509 >     &nresv_items, &cluster_items,  &service_items, &cresv_items, NULL
1510    };
1511  
1512    dlink_list ** iterator = free_items; /* C is dumb */
# Line 2467 | Line 1514 | clear_out_old_conf(void)
1514    /* We only need to free anything allocated by yyparse() here.
1515     * Resetting structs, etc, is taken care of by set_default_conf().
1516     */
1517 <  
1517 >
1518    for (; *iterator != NULL; iterator++)
1519    {
1520      DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1521      {
1522        conf = ptr->data;
2476      /* XXX This is less than pretty */
2477      if (conf->type == SERVER_TYPE)
2478      {
2479        aconf = map_to_conf(conf);
1523  
1524 <        if (aconf->clients != 0)
2482 <        {
2483 <          SetConfIllegal(aconf);
2484 <          dlinkDelete(&conf->node, &server_items);
2485 <        }
2486 <        else
2487 <        {
2488 <          delete_conf_item(conf);
2489 <        }
2490 <      }
2491 <      else if (conf->type == OPER_TYPE)
2492 <      {
2493 <        aconf = map_to_conf(conf);
1524 >      dlinkDelete(&conf->node, map_to_list(conf->type));
1525  
1526 <        if (aconf->clients != 0)
1527 <        {
2497 <          SetConfIllegal(aconf);
2498 <          dlinkDelete(&conf->node, &oconf_items);
2499 <        }
2500 <        else
2501 <        {
2502 <          delete_conf_item(conf);
2503 <        }
2504 <      }
2505 <      else if (conf->type == XLINE_TYPE  ||
2506 <               conf->type == RXLINE_TYPE ||
2507 <               conf->type == RKLINE_TYPE)
1526 >      /* XXX This is less than pretty */
1527 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1528        {
1529 <        /* temporary (r)xlines are also on
1530 <         * the (r)xconf items list */
2511 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2512 <          continue;
2513 <
2514 <        delete_conf_item(conf);
1529 >        if (!conf->ref_count)
1530 >          conf_free(conf);
1531        }
1532 <      else
1532 >      else if (conf->type == CONF_XLINE)
1533        {
1534 <        if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
1535 <        {
2520 <          match_item = map_to_conf(conf);
2521 <          if (match_item->ref_count <= 0)
2522 <            delete_conf_item(conf);
2523 <          else
2524 <          {
2525 <            match_item->illegal = 1;
2526 <            dlinkDelete(&conf->node, *iterator);
2527 <          }
2528 <        }
2529 <        else
2530 <          delete_conf_item(conf);
1534 >        if (!conf->until)
1535 >          conf_free(conf);
1536        }
1537 +      else
1538 +        conf_free(conf);
1539      }
1540    }
1541  
1542 +  motd_clear();
1543 +
1544    /*
1545     * don't delete the class table, rather mark all entries
1546 <   * for deletion. The table is cleaned up by check_class. - avalon
1546 >   * for deletion. The table is cleaned up by class_delete_marked. - avalon
1547     */
1548 <  DLINK_FOREACH(ptr, class_items.head)
2540 <  {
2541 <    cltmp = map_to_conf(ptr->data);
2542 <
2543 <    if (ptr != class_items.tail)  /* never mark the "default" class */
2544 <      cltmp->active = 0;
2545 <  }
1548 >  class_mark_for_deletion();
1549  
1550    clear_out_address_conf();
1551  
# Line 2559 | Line 1562 | clear_out_old_conf(void)
1562    MyFree(ConfigFileEntry.egdpool_path);
1563    ConfigFileEntry.egdpool_path = NULL;
1564   #ifdef HAVE_LIBCRYPTO
1565 <  if (ServerInfo.rsa_private_key != NULL)
1565 >  if (ServerInfo.rsa_private_key)
1566    {
1567      RSA_free(ServerInfo.rsa_private_key);
1568      ServerInfo.rsa_private_key = NULL;
# Line 2578 | Line 1581 | clear_out_old_conf(void)
1581                                                 SSL_OP_NO_TLSv1);
1582   #endif
1583  
2581  /* clean out old resvs from the conf */
2582  clear_conf_resv();
2583
1584    /* clean out AdminInfo */
1585    MyFree(AdminInfo.name);
1586    AdminInfo.name = NULL;
# Line 2589 | Line 1589 | clear_out_old_conf(void)
1589    MyFree(AdminInfo.description);
1590    AdminInfo.description = NULL;
1591  
2592  /* operator{} and class{} blocks are freed above */
1592    /* clean out listeners */
1593    close_listeners();
1594  
2596  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2597   * exempt{} and gecos{} blocks are freed above too
2598   */
2599
1595    /* clean out general */
1596    MyFree(ConfigFileEntry.service_name);
1597    ConfigFileEntry.service_name = NULL;
2603
2604  delete_isupport("INVEX");
2605  delete_isupport("EXCEPTS");
2606 }
2607
2608 /* flush_deleted_I_P()
2609 *
2610 * inputs       - none
2611 * output       - none
2612 * side effects - This function removes I/P conf items
2613 */
2614 static void
2615 flush_deleted_I_P(void)
2616 {
2617  dlink_node *ptr;
2618  dlink_node *next_ptr;
2619  struct ConfItem *conf;
2620  struct AccessItem *aconf;
2621  dlink_list * free_items [] = {
2622    &server_items, &oconf_items, NULL
2623  };
2624  dlink_list ** iterator = free_items; /* C is dumb */
2625
2626  /* flush out deleted I and P lines
2627   * although still in use.
2628   */
2629  for (; *iterator != NULL; iterator++)
2630  {
2631    DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2632    {
2633      conf = ptr->data;
2634      aconf = (struct AccessItem *)map_to_conf(conf);
2635
2636      if (IsConfIllegal(aconf))
2637      {
2638        dlinkDelete(ptr, *iterator);
2639
2640        if (aconf->clients == 0)
2641          delete_conf_item(conf);
2642      }
2643    }
2644  }
2645 }
2646
2647 /* get_conf_name()
2648 *
2649 * inputs       - type of conf file to return name of file for
2650 * output       - pointer to filename for type of conf
2651 * side effects - none
2652 */
2653 const char *
2654 get_conf_name(ConfType type)
2655 {
2656  switch (type)
2657  {
2658    case CONF_TYPE:
2659      return ConfigFileEntry.configfile;
2660      break;
2661    case KLINE_TYPE:
2662      return ConfigFileEntry.klinefile;
2663      break;
2664    case RKLINE_TYPE:
2665      return ConfigFileEntry.rklinefile;
2666      break;
2667    case DLINE_TYPE:
2668      return ConfigFileEntry.dlinefile;
2669      break;
2670    case XLINE_TYPE:
2671      return ConfigFileEntry.xlinefile;
2672      break;
2673    case RXLINE_TYPE:
2674      return ConfigFileEntry.rxlinefile;
2675      break;
2676    case CRESV_TYPE:
2677      return ConfigFileEntry.cresvfile;
2678      break;
2679    case NRESV_TYPE:
2680      return ConfigFileEntry.nresvfile;
2681      break;
2682    case GLINE_TYPE:
2683      return ConfigFileEntry.glinefile;
2684      break;
2685
2686    default:
2687      return NULL;  /* This should NEVER HAPPEN since we call this function
2688                       only with the above values, this will cause us to core
2689                       at some point if this happens so we know where it was */
2690  }
2691 }
2692
2693 #define BAD_PING (-1)
2694
2695 /* get_conf_ping()
2696 *
2697 * inputs       - pointer to struct AccessItem
2698 *              - pointer to a variable that receives ping warning time
2699 * output       - ping frequency
2700 * side effects - NONE
2701 */
2702 static int
2703 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2704 {
2705  struct ClassItem *aclass;
2706  struct AccessItem *aconf;
2707
2708  if (conf != NULL)
2709  {
2710    aconf = (struct AccessItem *)map_to_conf(conf);
2711    if (aconf->class_ptr != NULL)
2712    {
2713      aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2714      *pingwarn = aclass->ping_warning;
2715      return aclass->ping_freq;
2716    }
2717  }
2718
2719  return BAD_PING;
2720 }
2721
2722 /* get_client_class()
2723 *
2724 * inputs       - pointer to client struct
2725 * output       - pointer to name of class
2726 * side effects - NONE
2727 */
2728 const char *
2729 get_client_class(struct Client *target_p)
2730 {
2731  dlink_node *ptr;
2732  struct ConfItem *conf;
2733  struct AccessItem *aconf;
2734
2735  if (target_p != NULL && !IsMe(target_p) &&
2736      target_p->localClient->confs.head != NULL)
2737  {
2738    DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2739    {
2740      conf = ptr->data;
2741
2742      if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2743          conf->type == OPER_TYPE)
2744      {
2745        aconf = (struct AccessItem *) map_to_conf(conf);
2746        if (aconf->class_ptr != NULL)
2747          return aconf->class_ptr->name;
2748      }
2749    }
2750  }
2751
2752  return "default";
2753 }
2754
2755 /* get_client_ping()
2756 *
2757 * inputs       - pointer to client struct
2758 *              - pointer to a variable that receives ping warning time
2759 * output       - ping frequency
2760 * side effects - NONE
2761 */
2762 int
2763 get_client_ping(struct Client *target_p, int *pingwarn)
2764 {
2765  int ping;
2766  struct ConfItem *conf;
2767  dlink_node *nlink;
2768
2769  if (target_p->localClient->confs.head != NULL)
2770    DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2771    {
2772      conf = nlink->data;
2773
2774      if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2775          (conf->type == OPER_TYPE))
2776      {
2777        ping = get_conf_ping(conf, pingwarn);
2778        if (ping > 0)
2779          return ping;
2780      }
2781    }
2782
2783  *pingwarn = 0;
2784  return DEFAULT_PINGFREQUENCY;
2785 }
2786
2787 /* find_class()
2788 *
2789 * inputs       - string name of class
2790 * output       - corresponding Class pointer
2791 * side effects - NONE
2792 */
2793 struct ConfItem *
2794 find_class(const char *classname)
2795 {
2796  struct ConfItem *conf;
2797
2798  if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2799    return conf;
2800
2801  return class_default;
2802 }
2803
2804 /* check_class()
2805 *
2806 * inputs       - NONE
2807 * output       - NONE
2808 * side effects -
2809 */
2810 void
2811 check_class(void)
2812 {
2813  dlink_node *ptr = NULL, *next_ptr = NULL;
2814
2815  DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2816  {
2817    struct ClassItem *aclass = map_to_conf(ptr->data);
2818
2819    if (!aclass->active && !aclass->curr_user_count)
2820    {
2821      destroy_cidr_class(aclass);
2822      delete_conf_item(ptr->data);
2823    }
2824  }
2825 }
2826
2827 /* init_class()
2828 *
2829 * inputs       - NONE
2830 * output       - NONE
2831 * side effects -
2832 */
2833 void
2834 init_class(void)
2835 {
2836  struct ClassItem *aclass;
2837
2838  class_default = make_conf_item(CLASS_TYPE);
2839
2840  aclass = map_to_conf(class_default);
2841  aclass->active = 1;
2842  DupString(class_default->name, "default");
2843  aclass->con_freq  = DEFAULT_CONNECTFREQUENCY;
2844  aclass->ping_freq = DEFAULT_PINGFREQUENCY;
2845  aclass->max_total = MAXIMUM_LINKS_DEFAULT;
2846  aclass->max_sendq = DEFAULT_SENDQ;
2847
2848  client_check_cb = register_callback("check_client", check_client);
2849 }
2850
2851 /* get_sendq()
2852 *
2853 * inputs       - pointer to client
2854 * output       - sendq for this client as found from its class
2855 * side effects - NONE
2856 */
2857 unsigned int
2858 get_sendq(struct Client *client_p)
2859 {
2860  unsigned int sendq = DEFAULT_SENDQ;
2861  dlink_node *ptr;
2862  struct ConfItem *conf;
2863  struct ConfItem *class_conf;
2864  struct ClassItem *aclass;
2865  struct AccessItem *aconf;
2866
2867  if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2868  {
2869    DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2870    {
2871      conf = ptr->data;
2872      if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2873          || (conf->type == CLIENT_TYPE))
2874      {
2875        aconf = (struct AccessItem *)map_to_conf(conf);
2876        if ((class_conf = aconf->class_ptr) == NULL)
2877          continue;
2878        aclass = (struct ClassItem *)map_to_conf(class_conf);
2879        sendq = aclass->max_sendq;
2880        return sendq;
2881      }
2882    }
2883  }
2884  /* XXX return a default?
2885   * if here, then there wasn't an attached conf with a sendq
2886   * that is very bad -Dianora
2887   */
2888  return DEFAULT_SENDQ;
1598   }
1599  
1600   /* conf_add_class_to_conf()
1601   *
1602   * inputs       - pointer to config item
1603   * output       - NONE
1604 < * side effects - Add a class pointer to a conf
1604 > * side effects - Add a class pointer to a conf
1605   */
1606   void
1607 < conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
1607 > conf_add_class_to_conf(struct MaskItem *conf, const char *class_name)
1608   {
1609 <  struct AccessItem *aconf = map_to_conf(conf);
2901 <  struct ClassItem *class = NULL;
2902 <
2903 <  if (class_name == NULL)
1609 >  if (class_name == NULL)
1610    {
1611 <    aconf->class_ptr = class_default;
1611 >    conf->class = class_default;
1612  
1613 <    if (conf->type == CLIENT_TYPE)
1614 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1615 <                           "Warning *** Defaulting to default class for %s@%s",
1616 <                           aconf->user, aconf->host);
1613 >    if (conf->type == CONF_CLIENT)
1614 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1615 >                           "Warning *** Defaulting to default class for %s@%s",
1616 >                           conf->user, conf->host);
1617      else
1618 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1619 <                           "Warning *** Defaulting to default class for %s",
1620 <                           conf->name);
1618 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1619 >                           "Warning *** Defaulting to default class for %s",
1620 >                           conf->name);
1621    }
1622    else
1623 <    aconf->class_ptr = find_class(class_name);
1623 >    conf->class = class_find(class_name, 1);
1624  
1625 <  if (aconf->class_ptr)
2920 <    class = map_to_conf(aconf->class_ptr);
2921 <
2922 <  if (aconf->class_ptr == NULL || !class->active)
1625 >  if (conf->class == NULL)
1626    {
1627 <    if (conf->type == CLIENT_TYPE)
1628 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1629 <                           "Warning *** Defaulting to default class for %s@%s",
1630 <                           aconf->user, aconf->host);
1627 >    if (conf->type == CONF_CLIENT)
1628 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1629 >                           "Warning *** Defaulting to default class for %s@%s",
1630 >                           conf->user, conf->host);
1631      else
1632 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1633 <                           "Warning *** Defaulting to default class for %s",
1634 <                           conf->name);
1635 <    aconf->class_ptr = class_default;
1632 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1633 >                           "Warning *** Defaulting to default class for %s",
1634 >                           conf->name);
1635 >    conf->class = class_default;
1636    }
1637   }
1638  
2936 /* conf_add_server()
2937 *
2938 * inputs       - pointer to config item
2939 *              - pointer to link count already on this conf
2940 * output       - NONE
2941 * side effects - Add a connect block
2942 */
2943 int
2944 conf_add_server(struct ConfItem *conf, const char *class_name)
2945 {
2946  struct AccessItem *aconf = map_to_conf(conf);
2947
2948  conf_add_class_to_conf(conf, class_name);
2949
2950  if (!aconf->host || !conf->name)
2951  {
2952    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
2953    ilog(LOG_TYPE_IRCD, "Bad connect block");
2954    return -1;
2955  }
2956
2957  if (EmptyString(aconf->passwd))
2958  {
2959    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
2960                         conf->name);
2961    ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
2962    return -1;
2963  }
2964
2965  lookup_confhost(conf);
2966
2967  return 0;
2968 }
2969
1639   /* yyerror()
1640   *
1641   * inputs       - message from parser
# Line 2982 | Line 1651 | yyerror(const char *msg)
1651      return;
1652  
1653    strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1654 <  sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
1654 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1655 >                       "\"%s\", line %u: %s: %s",
1656 >                       conffilebuf, lineno + 1, msg, newlinebuf);
1657 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1658 >       conffilebuf, lineno + 1, msg, newlinebuf);
1659 > }
1660 >
1661 > void
1662 > conf_error_report(const char *msg)
1663 > {
1664 >  char newlinebuf[IRCD_BUFSIZE];
1665 >
1666 >  strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1667 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1668 >                       "\"%s\", line %u: %s: %s",
1669                         conffilebuf, lineno + 1, msg, newlinebuf);
1670    ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1671         conffilebuf, lineno + 1, msg, newlinebuf);
# Line 2990 | Line 1673 | yyerror(const char *msg)
1673  
1674   /*
1675   * valid_tkline()
1676 < *
1676 > *
1677   * inputs       - pointer to ascii string to check
1678   *              - whether the specified time is in seconds or minutes
1679   * output       - -1 not enough parameters
# Line 2999 | Line 1682 | yyerror(const char *msg)
1682   * Originally written by Dianora (Diane, db@db.net)
1683   */
1684   time_t
1685 < valid_tkline(const char *p, int minutes)
1685 > valid_tkline(const char *data, const int minutes)
1686   {
1687 +  const unsigned char *p = (const unsigned char *)data;
1688 +  unsigned char tmpch = '\0';
1689    time_t result = 0;
1690  
1691 <  for (; *p; ++p)
1691 >  while ((tmpch = *p++))
1692    {
1693 <    if (!IsDigit(*p))
1693 >    if (!IsDigit(tmpch))
1694        return 0;
1695  
1696      result *= 10;
1697 <    result += ((*p) & 0xF);
1697 >    result += (tmpch & 0xF);
1698    }
1699  
1700    /*
1701 <   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1701 >   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1702     * i.e. they specifically use 0, I am going to return 1 instead
1703     * as a return value of non-zero is used to flag it as a temporary kline
1704     */
1705    if (result == 0)
1706      result = 1;
1707  
1708 <  /*
1708 >  /*
1709     * If the incoming time is in seconds convert it to minutes for the purpose
1710     * of this calculation
1711     */
1712    if (!minutes)
1713 <    result = result / (time_t)60;
1713 >    result = result / 60;
1714  
1715    if (result > MAX_TDKLINE_TIME)
1716      result = MAX_TDKLINE_TIME;
1717  
1718 <  result = result * (time_t)60;  /* turn it into seconds */
1718 >  result = result * 60;  /* turn it into seconds */
1719  
1720    return result;
1721   }
1722  
1723 + /* valid_wild_card_simple()
1724 + *
1725 + * inputs       - data to check for sufficient non-wildcard characters
1726 + * outputs      - 1 if valid, else 0
1727 + * side effects - none
1728 + */
1729 + int
1730 + valid_wild_card_simple(const char *data)
1731 + {
1732 +  const unsigned char *p = (const unsigned char *)data;
1733 +  unsigned char tmpch = '\0';
1734 +  unsigned int nonwild = 0;
1735 +
1736 +  while ((tmpch = *p++))
1737 +  {
1738 +    if (tmpch == '\\')
1739 +    {
1740 +      ++p;
1741 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1742 +        return 1;
1743 +    }
1744 +    else if (!IsMWildChar(tmpch))
1745 +    {
1746 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1747 +        return 1;
1748 +    }
1749 +  }
1750 +
1751 +  return 0;
1752 + }
1753 +
1754   /* valid_wild_card()
1755   *
1756   * input        - pointer to client
# Line 3046 | Line 1762 | valid_tkline(const char *p, int minutes)
1762   int
1763   valid_wild_card(struct Client *source_p, int warn, int count, ...)
1764   {
1765 <  char *p;
1766 <  char tmpch;
3051 <  int nonwild = 0;
1765 >  unsigned char tmpch = '\0';
1766 >  unsigned int nonwild = 0;
1767    va_list args;
1768  
1769    /*
# Line 3067 | Line 1782 | valid_wild_card(struct Client *source_p,
1782  
1783    while (count--)
1784    {
1785 <    p = va_arg(args, char *);
1785 >    const unsigned char *p = va_arg(args, const unsigned char *);
1786      if (p == NULL)
1787        continue;
1788  
# Line 3080 | Line 1795 | valid_wild_card(struct Client *source_p,
1795           * break - no point in searching further.
1796           */
1797          if (++nonwild >= ConfigFileEntry.min_nonwildcard)
1798 +        {
1799 +          va_end(args);
1800            return 1;
1801 +        }
1802        }
1803      }
1804    }
1805  
1806    if (warn)
1807 <    sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
1808 <               me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
1807 >    sendto_one_notice(source_p, &me,
1808 >                      ":Please include at least %u non-wildcard characters with the mask",
1809 >                      ConfigFileEntry.min_nonwildcard);
1810 >  va_end(args);
1811    return 0;
1812   }
1813  
# Line 3101 | Line 1821 | valid_wild_card(struct Client *source_p,
1821   *              - parse_flags bit map of things to test
1822   *              - pointer to user or string to parse into
1823   *              - pointer to host or NULL to parse into if non NULL
1824 < *              - pointer to optional tkline time or NULL
1824 > *              - pointer to optional tkline time or NULL
1825   *              - pointer to target_server to parse into if non NULL
1826   *              - pointer to reason to parse into
1827   *
# Line 3123 | Line 1843 | valid_wild_card(struct Client *source_p,
1843   */
1844   int
1845   parse_aline(const char *cmd, struct Client *source_p,
1846 <            int parc, char **parv,
1847 <            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1848 <            char **target_server, char **reason)
1846 >            int parc, char **parv,
1847 >            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1848 >            char **target_server, char **reason)
1849   {
1850    int found_tkline_time=0;
1851 <  static char def_reason[] = "No Reason";
1851 >  static char def_reason[] = CONF_NOREASON;
1852    static char user[USERLEN*4+1];
1853    static char host[HOSTLEN*4+1];
1854  
# Line 3146 | Line 1866 | parse_aline(const char *cmd, struct Clie
1866        *tkline_time = found_tkline_time;
1867      else
1868      {
1869 <      sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3150 <                 me.name, source_p->name, cmd);
1869 >      sendto_one_notice(source_p, &me, ":temp_line not supported by %s", cmd);
1870        return -1;
1871      }
1872    }
1873  
1874    if (parc == 0)
1875    {
1876 <    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3158 <               me.name, source_p->name, cmd);
1876 >    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1877      return -1;
1878    }
1879  
# Line 3169 | Line 1887 | parse_aline(const char *cmd, struct Clie
1887      *up_p = user;
1888      *h_p = host;
1889    }
1890 <
1890 >
1891    parc--;
1892    parv++;
1893  
# Line 3182 | Line 1900 | parse_aline(const char *cmd, struct Clie
1900  
1901        if (target_server == NULL)
1902        {
1903 <        sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
1904 <                   me.name, source_p->name, cmd);
3187 <        return -1;
1903 >        sendto_one_notice(source_p, &me, ":ON server not supported by %s", cmd);
1904 >        return -1;
1905        }
1906  
1907        if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
1908        {
1909 <        sendto_one(source_p, form_str(ERR_NOPRIVS),
3193 <                   me.name, source_p->name, "remoteban");
1909 >        sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "remoteban");
1910          return -1;
1911        }
1912  
1913        if (parc == 0 || EmptyString(*parv))
1914        {
1915 <        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1916 <                   me.name, source_p->name, cmd);
3201 <        return -1;
1915 >        sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1916 >        return -1;
1917        }
1918  
1919        *target_server = *parv;
# Line 3211 | Line 1926 | parse_aline(const char *cmd, struct Clie
1926         * caller probably NULL'd it first, but no harm to do it again -db
1927         */
1928        if (target_server != NULL)
1929 <        *target_server = NULL;
1929 >        *target_server = NULL;
1930      }
1931    }
1932  
# Line 3219 | Line 1934 | parse_aline(const char *cmd, struct Clie
1934    {
1935      if (strchr(user, '!') != NULL)
1936      {
1937 <      sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3223 <                 me.name, source_p->name);
1937 >      sendto_one_notice(source_p, &me, ":Invalid character '!' in kline");
1938        return -1;
1939      }
1940  
# Line 3237 | Line 1951 | parse_aline(const char *cmd, struct Clie
1951      {
1952        *reason = *parv;
1953        if (!valid_comment(source_p, *reason, 1))
1954 <        return -1;
1954 >        return -1;
1955      }
1956      else
1957        *reason = def_reason;
# Line 3276 | Line 1990 | find_user_host(struct Client *source_p,
1990      {
1991        *(hostp++) = '\0';                       /* short and squat */
1992        if (*user_host_or_nick)
1993 <        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
1993 >        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
1994        else
1995 <        strcpy(luser, "*");
1995 >        strcpy(luser, "*");
1996 >
1997        if (*hostp)
1998 <        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
1998 >        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
1999        else
2000 <        strcpy(lhost, "*");
2000 >        strcpy(lhost, "*");
2001      }
2002      else
2003      {
2004        luser[0] = '*';             /* no @ found, assume its *@somehost */
2005 <      luser[1] = '\0';    
2005 >      luser[1] = '\0';
2006        strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
2007      }
2008 <    
2008 >
2009      return 1;
2010    }
2011 <  else if (!(flags & NOUSERLOOKUP))
2011 >  else
2012    {
2013      /* Try to find user@host mask from nick */
2014      /* Okay to use source_p as the first param, because source_p == client_p */
2015 <    if ((target_p =
2016 <        find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
2017 <      return 0;
2015 >    if ((target_p =
2016 >        find_chasing(source_p, user_host_or_nick)) == NULL)
2017 >      return 0;  /* find_chasing sends ERR_NOSUCHNICK */
2018  
2019      if (IsExemptKline(target_p))
2020      {
2021        if (!IsServer(source_p))
2022 <        sendto_one(source_p,
3308 <                   ":%s NOTICE %s :%s is E-lined",
3309 <                   me.name, source_p->name, target_p->name);
2022 >        sendto_one_notice(source_p, &me, ":%s is E-lined", target_p->name);
2023        return 0;
2024      }
2025  
# Line 3341 | Line 2054 | find_user_host(struct Client *source_p,
2054   int
2055   valid_comment(struct Client *source_p, char *comment, int warn)
2056   {
3344  if (strchr(comment, '"'))
3345  {
3346    if (warn)
3347      sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3348                 me.name, source_p->name);
3349    return 0;
3350  }
3351
2057    if (strlen(comment) > REASONLEN)
2058      comment[REASONLEN-1] = '\0';
2059  
# Line 3363 | Line 2068 | valid_comment(struct Client *source_p, c
2068   * side effects - none
2069   */
2070   int
2071 < match_conf_password(const char *password, const struct AccessItem *aconf)
2071 > match_conf_password(const char *password, const struct MaskItem *conf)
2072   {
2073    const char *encr = NULL;
2074  
2075 <  if (password == NULL || aconf->passwd == NULL)
2075 >  if (EmptyString(password) || EmptyString(conf->passwd))
2076      return 0;
2077  
2078 <  if (aconf->flags & CONF_FLAGS_ENCRYPTED)
2079 <  {
3375 <    /* use first two chars of the password they send in as salt */
3376 <    /* If the password in the conf is MD5, and ircd is linked
3377 <     * to scrypt on FreeBSD, or the standard crypt library on
3378 <     * glibc Linux, then this code will work fine on generating
3379 <     * the proper encrypted hash for comparison.
3380 <     */
3381 <    if (*aconf->passwd)
3382 <      encr = crypt(password, aconf->passwd);
3383 <    else
3384 <      encr = "";
3385 <  }
2078 >  if (conf->flags & CONF_FLAGS_ENCRYPTED)
2079 >    encr = crypt(password, conf->passwd);
2080    else
2081      encr = password;
2082  
2083 <  return !strcmp(encr, aconf->passwd);
2083 >  return encr && !strcmp(encr, conf->passwd);
2084   }
2085  
2086   /*
# Line 3394 | Line 2088 | match_conf_password(const char *password
2088   *
2089   * inputs       - client sending the cluster
2090   *              - command name "KLINE" "XLINE" etc.
2091 < *              - capab -- CAP_KLN etc. from s_serv.h
2091 > *              - capab -- CAP_KLN etc. from server.h
2092   *              - cluster type -- CLUSTER_KLINE etc. from conf.h
2093   *              - pattern and args to send along
2094   * output       - none
# Line 3406 | Line 2100 | cluster_a_line(struct Client *source_p,
2100                 int capab, int cluster_type, const char *pattern, ...)
2101   {
2102    va_list args;
2103 <  char buffer[IRCD_BUFSIZE];
2103 >  char buffer[IRCD_BUFSIZE] = "";
2104    const dlink_node *ptr = NULL;
2105  
2106    va_start(args, pattern);
# Line 3415 | Line 2109 | cluster_a_line(struct Client *source_p,
2109  
2110    DLINK_FOREACH(ptr, cluster_items.head)
2111    {
2112 <    const struct ConfItem *conf = ptr->data;
2112 >    const struct MaskItem *conf = ptr->data;
2113  
2114      if (conf->flags & cluster_type)
2115        sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
2116 <                         "%s %s %s", command, conf->name, buffer);
2116 >                         "%s %s %s", command, conf->name, buffer);
2117    }
2118   }
2119  
# Line 3467 | Line 2161 | split_nuh(struct split_nuh_item *const i
2161    {
2162      *p = '\0';
2163  
2164 <    if (iptr->nickptr && *iptr->nuhmask != '\0')
2164 >    if (iptr->nickptr && *iptr->nuhmask)
2165        strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
2166  
2167 <    if ((q = strchr(++p, '@'))) {
2167 >    if ((q = strchr(++p, '@')))
2168 >    {
2169        *q++ = '\0';
2170  
2171 <      if (*p != '\0')
2171 >      if (*p)
2172          strlcpy(iptr->userptr, p, iptr->usersize);
2173  
2174 <      if (*q != '\0')
2174 >      if (*q)
2175          strlcpy(iptr->hostptr, q, iptr->hostsize);
2176      }
2177      else
2178      {
2179 <      if (*p != '\0')
2179 >      if (*p)
2180          strlcpy(iptr->userptr, p, iptr->usersize);
2181      }
2182    }
# Line 3493 | Line 2188 | split_nuh(struct split_nuh_item *const i
2188        /* if found a @ */
2189        *p++ = '\0';
2190  
2191 <      if (*iptr->nuhmask != '\0')
2191 >      if (*iptr->nuhmask)
2192          strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
2193  
2194 <      if (*p != '\0')
2194 >      if (*p)
2195          strlcpy(iptr->hostptr, p, iptr->hostsize);
2196      }
2197      else
# Line 3509 | Line 2204 | split_nuh(struct split_nuh_item *const i
2204      }
2205    }
2206   }
3512
3513 /*
3514 * flags_to_ascii
3515 *
3516 * inputs       - flags is a bitmask
3517 *              - pointer to table of ascii letters corresponding
3518 *                to each bit
3519 *              - flag 1 for convert ToLower if bit missing
3520 *                0 if ignore.
3521 * output       - none
3522 * side effects - string pointed to by p has bitmap chars written to it
3523 */
3524 static void
3525 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3526               int lowerit)
3527 {
3528  unsigned int mask = 1;
3529  int i = 0;
3530
3531  for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3532  {
3533    if (flags & mask)
3534      *p++ = bit_table[i];
3535    else if (lowerit)
3536      *p++ = ToLower(bit_table[i]);
3537  }
3538  *p = '\0';
3539 }
3540
3541 /*
3542 * cidr_limit_reached
3543 *
3544 * inputs       - int flag allowing over_rule of limits
3545 *              - pointer to the ip to be added
3546 *              - pointer to the class
3547 * output       - non zero if limit reached
3548 *                0 if limit not reached
3549 * side effects -
3550 */
3551 static int
3552 cidr_limit_reached(int over_rule,
3553                   struct irc_ssaddr *ip, struct ClassItem *aclass)
3554 {
3555  dlink_node *ptr = NULL;
3556  struct CidrItem *cidr;
3557
3558  if (aclass->number_per_cidr <= 0)
3559    return 0;
3560
3561  if (ip->ss.ss_family == AF_INET)
3562  {
3563    if (aclass->cidr_bitlen_ipv4 <= 0)
3564      return 0;
3565
3566    DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3567    {
3568      cidr = ptr->data;
3569      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3570      {
3571        if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3572          return -1;
3573        cidr->number_on_this_cidr++;
3574        return 0;
3575      }
3576    }
3577    cidr = MyMalloc(sizeof(struct CidrItem));
3578    cidr->number_on_this_cidr = 1;
3579    cidr->mask = *ip;
3580    mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv4);
3581    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3582  }
3583 #ifdef IPV6
3584  else if (aclass->cidr_bitlen_ipv6 > 0)
3585  {
3586    DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3587    {
3588      cidr = ptr->data;
3589      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3590      {
3591        if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3592          return -1;
3593        cidr->number_on_this_cidr++;
3594        return 0;
3595      }
3596    }
3597    cidr = MyMalloc(sizeof(struct CidrItem));
3598    cidr->number_on_this_cidr = 1;
3599    cidr->mask = *ip;
3600    mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv6);
3601    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3602  }
3603 #endif
3604  return 0;
3605 }
3606
3607 /*
3608 * remove_from_cidr_check
3609 *
3610 * inputs       - pointer to the ip to be removed
3611 *              - pointer to the class
3612 * output       - NONE
3613 * side effects -
3614 */
3615 static void
3616 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3617 {
3618  dlink_node *ptr = NULL;
3619  dlink_node *next_ptr = NULL;
3620  struct CidrItem *cidr;
3621
3622  if (aclass->number_per_cidr == 0)
3623    return;
3624
3625  if (ip->ss.ss_family == AF_INET)
3626  {
3627    if (aclass->cidr_bitlen_ipv4 <= 0)
3628      return;
3629
3630    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3631    {
3632      cidr = ptr->data;
3633      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3634      {
3635        cidr->number_on_this_cidr--;
3636        if (cidr->number_on_this_cidr == 0)
3637        {
3638          dlinkDelete(ptr, &aclass->list_ipv4);
3639          MyFree(cidr);
3640          return;
3641        }
3642      }
3643    }
3644  }
3645 #ifdef IPV6
3646  else if (aclass->cidr_bitlen_ipv6 > 0)
3647  {
3648    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3649    {
3650      cidr = ptr->data;
3651      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3652      {
3653        cidr->number_on_this_cidr--;
3654        if (cidr->number_on_this_cidr == 0)
3655        {
3656          dlinkDelete(ptr, &aclass->list_ipv6);
3657          MyFree(cidr);
3658          return;
3659        }
3660      }
3661    }
3662  }
3663 #endif
3664 }
3665
3666 static void
3667 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3668                  dlink_list *old_list, dlink_list *new_list, int changed)
3669 {
3670  dlink_node *ptr;
3671  struct Client *client_p;
3672  struct ConfItem *conf;
3673  struct AccessItem *aconf;
3674
3675  if (!changed)
3676  {
3677    *new_list = *old_list;
3678    old_list->head = old_list->tail = NULL;
3679    old_list->length = 0;
3680    return;
3681  }
3682
3683  DLINK_FOREACH(ptr, local_client_list.head)
3684  {
3685    client_p = ptr->data;
3686    if (client_p->localClient->aftype != aftype)
3687      continue;
3688    if (dlink_list_length(&client_p->localClient->confs) == 0)
3689      continue;
3690
3691    conf = client_p->localClient->confs.tail->data;
3692    if (conf->type == CLIENT_TYPE)
3693    {
3694      aconf = map_to_conf(conf);
3695      if (aconf->class_ptr == oldcl)
3696        cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3697    }
3698  }
3699 }
3700
3701 /*
3702 * rebuild_cidr_class
3703 *
3704 * inputs       - pointer to old conf
3705 *              - pointer to new_class
3706 * output       - none
3707 * side effects - rebuilds the class link list of cidr blocks
3708 */
3709 void
3710 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3711 {
3712  struct ClassItem *old_class = map_to_conf(conf);
3713
3714  if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
3715  {
3716    if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
3717      rebuild_cidr_list(AF_INET, conf, new_class,
3718                        &old_class->list_ipv4, &new_class->list_ipv4,
3719                        old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
3720
3721 #ifdef IPV6
3722    if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
3723      rebuild_cidr_list(AF_INET6, conf, new_class,
3724                        &old_class->list_ipv6, &new_class->list_ipv6,
3725                        old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
3726 #endif
3727  }
3728
3729  destroy_cidr_class(old_class);
3730 }
3731
3732 /*
3733 * destroy_cidr_list
3734 *
3735 * inputs       - pointer to class dlink list of cidr blocks
3736 * output       - none
3737 * side effects - completely destroys the class link list of cidr blocks
3738 */
3739 static void
3740 destroy_cidr_list(dlink_list *list)
3741 {
3742  dlink_node *ptr = NULL, *next_ptr = NULL;
3743
3744  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3745  {
3746    dlinkDelete(ptr, list);
3747    MyFree(ptr->data);
3748  }
3749 }
3750
3751 /*
3752 * destroy_cidr_class
3753 *
3754 * inputs       - pointer to class
3755 * output       - none
3756 * side effects - completely destroys the class link list of cidr blocks
3757 */
3758 static void
3759 destroy_cidr_class(struct ClassItem *aclass)
3760 {
3761  destroy_cidr_list(&aclass->list_ipv4);
3762  destroy_cidr_list(&aclass->list_ipv6);
3763 }

Diff Legend

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