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/s_conf.c (file contents), Revision 1247 by michael, Sat Oct 1 07:54:24 2011 UTC vs.
ircd-hybrid/trunk/src/conf.c (file contents), Revision 4313 by michael, Thu Jul 31 18:50:11 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  s_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"
30 < #include "balloc.h"
31 < #include "s_conf.h"
30 < #include "s_serv.h"
30 > #include "conf.h"
31 > #include "server.h"
32   #include "resv.h"
33   #include "channel.h"
34   #include "client.h"
35   #include "event.h"
35 #include "hash.h"
36 #include "hook.h"
36   #include "irc_string.h"
38 #include "sprintf_irc.h"
37   #include "s_bsd.h"
38   #include "ircd.h"
39   #include "listener.h"
# Line 43 | Line 41
41   #include "modules.h"
42   #include "numeric.h"
43   #include "fdlist.h"
44 < #include "s_log.h"
44 > #include "log.h"
45   #include "send.h"
48 #include "s_gline.h"
49 #include "fileio.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  
58 struct Callback *client_check_cb = NULL;
59 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 };
65 dlink_list hub_items     = { NULL, NULL, 0 };
66 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 };
70 dlink_list rxconf_items  = { NULL, NULL, 0 };
71 dlink_list rkconf_items  = { NULL, NULL, 0 };
66   dlink_list nresv_items   = { NULL, NULL, 0 };
67 < dlink_list class_items   = { NULL, NULL, 0 };
74 < dlink_list gdeny_items   = { NULL, NULL, 0 };
75 <
76 < dlink_list temporary_klines  = { NULL, NULL, 0 };
77 < dlink_list temporary_dlines  = { NULL, NULL, 0 };
78 < dlink_list temporary_xlines  = { NULL, NULL, 0 };
79 < dlink_list temporary_rklines = { NULL, NULL, 0 };
80 < dlink_list temporary_glines  = { NULL, NULL, 0 };
81 < dlink_list temporary_rxlines = { NULL, NULL, 0 };
82 < 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];
87 extern char yytext[];
72   extern int yyparse(); /* defined in y.tab.c */
73  
90 struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
91
74   /* internally defined functions */
75 < static void lookup_confhost(struct ConfItem *);
94 < static void set_default_conf(void);
95 < static void validate_conf(void);
96 < static void read_conf(FBFILE *);
75 > static void read_conf(FILE *);
76   static void clear_out_old_conf(void);
98 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);
106 < static dlink_list *map_to_list(ConfType);
107 < 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  
110 /*
111 * bit_len
112 */
113 static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
114 static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
115 static void destroy_cidr_class(struct ClassItem *);
116
117 static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
118
119 /* address of default class conf */
120 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 128 | 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  
141 void *
142 map_to_conf(struct ConfItem *aconf)
143 {
144  void *conf;
145  conf = (void *)((uintptr_t)aconf +
146                  (uintptr_t)sizeof(struct ConfItem));
147  return(conf);
148 }
149
150 struct ConfItem *
151 unmap_conf_item(void *aconf)
152 {
153  struct ConfItem *conf;
154
155  conf = (struct ConfItem *)((uintptr_t)aconf -
156                             (uintptr_t)sizeof(struct ConfItem));
157  return(conf);
158 }
159
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 170 | 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 187 | 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 < *
201 < * inputs       - type of item
202 < * output       - pointer to new conf entry
203 < * side effects - none
204 < */
205 < struct ConfItem *
206 < 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;
210 <  struct ClassItem *aclass = NULL;
211 <  int status = 0;
212 <
213 <  switch (type)
214 <  {
215 <  case DLINE_TYPE:
216 <  case EXEMPTDLINE_TYPE:
217 <  case GLINE_TYPE:
218 <  case KLINE_TYPE:
219 <  case CLIENT_TYPE:
220 <  case OPER_TYPE:
221 <  case SERVER_TYPE:
222 <    conf = MyMalloc(sizeof(struct ConfItem) +
223 <                    sizeof(struct AccessItem));
224 <    aconf = map_to_conf(conf);
225 <    aconf->aftype = AF_INET;
226 <
227 <    /* Yes, sigh. switch on type again */
228 <    switch (type)
229 <    {
230 <    case EXEMPTDLINE_TYPE:
231 <      status = CONF_EXEMPTDLINE;
232 <      break;
233 <
234 <    case DLINE_TYPE:
235 <      status = CONF_DLINE;
236 <      break;
237 <
238 <    case KLINE_TYPE:
239 <      status = CONF_KLINE;
240 <      break;
241 <
242 <    case GLINE_TYPE:
243 <      status = CONF_GLINE;
244 <      break;
245 <
246 <    case CLIENT_TYPE:
247 <      status = CONF_CLIENT;
248 <      break;
249 <
250 <    case OPER_TYPE:
251 <      status = CONF_OPERATOR;
252 <      dlinkAdd(conf, &conf->node, &oconf_items);
253 <      break;
254 <
255 <    case SERVER_TYPE:
256 <      status = CONF_SERVER;
257 <      dlinkAdd(conf, &conf->node, &server_items);
258 <      break;
259 <
260 <    default:
261 <      break;
262 <    }
263 <    aconf->status = status;
264 <    break;
265 <
266 <  case LEAF_TYPE:
267 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
268 <                                       sizeof(struct MatchItem));
269 <    dlinkAdd(conf, &conf->node, &leaf_items);
270 <    break;
271 <
272 <  case HUB_TYPE:
273 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
274 <                                       sizeof(struct MatchItem));
275 <    dlinkAdd(conf, &conf->node, &hub_items);
276 <    break;
277 <
278 <  case ULINE_TYPE:
279 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
280 <                                       sizeof(struct MatchItem));
281 <    dlinkAdd(conf, &conf->node, &uconf_items);
282 <    break;
283 <
284 <  case GDENY_TYPE:
285 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
286 <                                       sizeof(struct AccessItem));
287 <    dlinkAdd(conf, &conf->node, &gdeny_items);
288 <    break;
289 <
290 <  case XLINE_TYPE:
291 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
292 <                                       sizeof(struct MatchItem));
293 <    dlinkAdd(conf, &conf->node, &xconf_items);
294 <    break;
295 < #ifdef HAVE_LIBPCRE
296 <  case RXLINE_TYPE:
297 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
298 <                                       sizeof(struct MatchItem));
299 <    dlinkAdd(conf, &conf->node, &rxconf_items);
300 <    break;
301 <
302 <  case RKLINE_TYPE:
303 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
304 <                                       sizeof(struct AccessItem));
305 <    aconf = map_to_conf(conf);
306 <    aconf->status = CONF_KLINE;
307 <    dlinkAdd(conf, &conf->node, &rkconf_items);
308 <    break;
309 < #endif
310 <  case CLUSTER_TYPE:
311 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
312 <    dlinkAdd(conf, &conf->node, &cluster_items);
313 <    break;
314 <
315 <  case CRESV_TYPE:
316 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
317 <                                       sizeof(struct ResvChannel));
318 <    break;
319 <
320 <  case NRESV_TYPE:
321 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
322 <                                       sizeof(struct MatchItem));
323 <    dlinkAdd(conf, &conf->node, &nresv_items);
324 <    break;
325 <
326 <  case SERVICE_TYPE:
327 <    status = CONF_SERVICE;
328 <    conf = MyMalloc(sizeof(struct ConfItem));
329 <    dlinkAdd(conf, &conf->node, &service_items);
330 <    break;
331 <
332 <  case CLASS_TYPE:
333 <    conf = MyMalloc(sizeof(struct ConfItem) +
334 <                           sizeof(struct ClassItem));
335 <    dlinkAdd(conf, &conf->node, &class_items);
336 <
337 <    aclass = map_to_conf(conf);
338 <    aclass->active = 1;
339 <    ConFreq(aclass) = DEFAULT_CONNECTFREQUENCY;
340 <    PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
341 <    MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
342 <    MaxSendq(aclass) = DEFAULT_SENDQ;
343 <
344 <    break;
149 >  struct MaskItem *conf = MyCalloc(sizeof(*conf));
150 >  dlink_list *list = NULL;
151  
152 <  default:
153 <    conf = NULL;
154 <    break;
349 <  }
350 <
351 <  /* XXX Yes, this will core if default is hit. I want it to for now - db */
352 <  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);
366  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));
383 <    if (aconf->spasswd != NULL)
384 <      memset(aconf->spasswd, 0, strlen(aconf->spasswd));
385 <    aconf->class_ptr = NULL;
386 <
387 <    MyFree(aconf->passwd);
388 <    MyFree(aconf->spasswd);
389 <    MyFree(aconf->reason);
390 <    MyFree(aconf->oper_reason);
391 <    MyFree(aconf->user);
392 <    MyFree(aconf->host);
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)
395 <      RSA_free(aconf->rsa_public_key);
396 <    MyFree(aconf->rsa_public_key_file);
397 < #endif
398 <
399 <    /* Yes, sigh. switch on type again */
400 <    switch(type)
401 <    {
402 <    case EXEMPTDLINE_TYPE:
403 <    case DLINE_TYPE:
404 <    case GLINE_TYPE:
405 <    case KLINE_TYPE:
406 <    case CLIENT_TYPE:
407 <      MyFree(conf);
408 <      break;
409 <
410 <    case OPER_TYPE:
411 <      aconf = map_to_conf(conf);
412 <      if (!IsConfIllegal(aconf))
413 <        dlinkDelete(&conf->node, &oconf_items);
414 <      MyFree(conf);
415 <      break;
416 <
417 <    case SERVER_TYPE:
418 <      aconf = map_to_conf(conf);
419 <      if (!IsConfIllegal(aconf))
420 <        dlinkDelete(&conf->node, &server_items);
421 <      MyFree(conf);
422 <      break;
423 <
424 <    default:
425 <      break;
426 <    }
427 <    break;
428 <
429 <  case HUB_TYPE:
430 <    match_item = map_to_conf(conf);
431 <    MyFree(match_item->user);
432 <    MyFree(match_item->host);
433 <    MyFree(match_item->reason);
434 <    MyFree(match_item->oper_reason);
435 <    /* If marked illegal, its already been pulled off of the hub_items list */
436 <    if (!match_item->illegal)
437 <      dlinkDelete(&conf->node, &hub_items);
438 <    MyFree(conf);
439 <    break;
440 <
441 <  case LEAF_TYPE:
442 <    match_item = map_to_conf(conf);
443 <    MyFree(match_item->user);
444 <    MyFree(match_item->host);
445 <    MyFree(match_item->reason);
446 <    MyFree(match_item->oper_reason);
447 <    /* If marked illegal, its already been pulled off of the leaf_items list */
448 <    if (!match_item->illegal)
449 <      dlinkDelete(&conf->node, &leaf_items);
450 <    MyFree(conf);
451 <    break;
189 >  MyFree(conf->cipher_list);
190  
191 <  case ULINE_TYPE:
192 <    match_item = map_to_conf(conf);
455 <    MyFree(match_item->user);
456 <    MyFree(match_item->host);
457 <    MyFree(match_item->reason);
458 <    MyFree(match_item->oper_reason);
459 <    dlinkDelete(&conf->node, &uconf_items);
460 <    MyFree(conf);
461 <    break;
462 <
463 <  case XLINE_TYPE:
464 <    match_item = map_to_conf(conf);
465 <    MyFree(match_item->user);
466 <    MyFree(match_item->host);
467 <    MyFree(match_item->reason);
468 <    MyFree(match_item->oper_reason);
469 <    dlinkDelete(&conf->node, &xconf_items);
470 <    MyFree(conf);
471 <    break;
472 < #ifdef HAVE_LIBPCRE
473 <  case RKLINE_TYPE:
474 <    aconf = map_to_conf(conf);
475 <    MyFree(aconf->regexuser);
476 <    MyFree(aconf->regexhost);
477 <    MyFree(aconf->user);
478 <    MyFree(aconf->host);
479 <    MyFree(aconf->reason);
480 <    MyFree(aconf->oper_reason);
481 <    dlinkDelete(&conf->node, &rkconf_items);
482 <    MyFree(conf);
483 <    break;
484 <
485 <  case RXLINE_TYPE:
486 <    MyFree(conf->regexpname);
487 <    match_item = map_to_conf(conf);
488 <    MyFree(match_item->user);
489 <    MyFree(match_item->host);
490 <    MyFree(match_item->reason);
491 <    MyFree(match_item->oper_reason);
492 <    dlinkDelete(&conf->node, &rxconf_items);
493 <    MyFree(conf);
494 <    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);
501 <    MyFree(match_item->oper_reason);
502 <    dlinkDelete(&conf->node, &nresv_items);
503 <
504 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
505 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
506 <        free_dlink_node(m);
507 <
508 <    MyFree(conf);
509 <    break;
510 <
511 <  case GDENY_TYPE:
512 <    aconf = map_to_conf(conf);
513 <    MyFree(aconf->user);
514 <    MyFree(aconf->host);
515 <    dlinkDelete(&conf->node, &gdeny_items);
516 <    MyFree(conf);
517 <    break;
518 <
519 <  case CLUSTER_TYPE:
520 <    dlinkDelete(&conf->node, &cluster_items);
521 <    MyFree(conf);
522 <    break;
523 <
524 <  case CRESV_TYPE:
525 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
526 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
527 <        free_dlink_node(m);
528 <
529 <    MyFree(conf);
530 <    break;
531 <
532 <  case CLASS_TYPE:
533 <    dlinkDelete(&conf->node, &class_items);
534 <    MyFree(conf);
535 <    break;
536 <
537 <  case SERVICE_TYPE:
538 <    dlinkDelete(&conf->node, &service_items);
539 <    MyFree(conf);
540 <    break;
541 <
542 <  default:
543 <    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    }
545 }
546
547 /* free_access_item()
548 *
549 * inputs       - pointer to conf to free
550 * output       - none
551 * side effects - crucial password fields are zeroed, conf is freed
552 */
553 void
554 free_access_item(struct AccessItem *aconf)
555 {
556  struct ConfItem *conf;
557
558  if (aconf == NULL)
559    return;
560  conf = unmap_conf_item(aconf);
561  delete_conf_item(conf);
562 }
200  
201 < static const unsigned int shared_bit_table[] =
565 <  { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
566 <
567 < /* report_confitem_types()
568 < *
569 < * inputs       - pointer to client requesting confitem report
570 < *              - ConfType to report
571 < * output       - none
572 < * side effects -
573 < */
574 < void
575 < report_confitem_types(struct Client *source_p, ConfType type, int temp)
576 < {
577 <  dlink_node *ptr = NULL;
578 <  struct ConfItem *conf = NULL;
579 <  struct AccessItem *aconf = NULL;
580 <  struct MatchItem *matchitem = NULL;
581 <  struct ClassItem *classitem = NULL;
582 <  char buf[12];
583 <  char *p = NULL;
584 <  const char *pfx = NULL;
585 <
586 <  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;
592 <      aconf = map_to_conf(conf);
593 <
594 <      p = buf;
595 <
596 <      if (aconf->flags & GDENY_BLOCK)
597 <        *p++ = 'B';
598 <      else
599 <        *p++ = 'b';
600 <
601 <      if (aconf->flags & GDENY_REJECT)
602 <        *p++ = 'R';
603 <      else
604 <        *p++ = 'r';
605 <
606 <      *p = '\0';
607 <
608 <      sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
609 <                 me.name, RPL_STATSDEBUG, source_p->name,
610 <                 aconf->user, aconf->host, conf->name, buf);
611 <    }
612 <    break;
613 <
614 <  case XLINE_TYPE:
615 <    DLINK_FOREACH(ptr, xconf_items.head)
616 <    {
617 <      conf = ptr->data;
618 <      matchitem = map_to_conf(conf);
619 <
620 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
621 <                 me.name, source_p->name,
622 <                 matchitem->hold ? "x": "X", matchitem->count,
623 <                 conf->name, matchitem->reason);
624 <    }
625 <    break;
626 <
627 < #ifdef HAVE_LIBPCRE
628 <  case RXLINE_TYPE:
629 <    DLINK_FOREACH(ptr, rxconf_items.head)
630 <    {
631 <      conf = ptr->data;
632 <      matchitem = map_to_conf(conf);
633 <
634 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
635 <                 me.name, source_p->name,
636 <                 matchitem->hold ? "xR": "XR", matchitem->count,
637 <                 conf->name, matchitem->reason);
638 <    }
639 <    break;
640 <
641 <  case RKLINE_TYPE:
642 <    pfx = temp ? "kR" : "KR";
643 <
644 <    DLINK_FOREACH(ptr, rkconf_items.head)
645 <    {
646 <      aconf = map_to_conf((conf = ptr->data));
647 <
648 <      if (temp && !(conf->flags & CONF_FLAGS_TEMPORARY))
649 <        continue;
650 <
651 <      sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
652 <                 source_p->name, pfx, aconf->host, aconf->user,
653 <                 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
654 <    }
655 <    break;
656 < #endif
657 <
658 <  case ULINE_TYPE:
659 <    DLINK_FOREACH(ptr, uconf_items.head)
660 <    {
661 <      conf = ptr->data;
662 <      matchitem = map_to_conf(conf);
663 <
664 <      p = buf;
665 <
666 <      /* some of these are redundant for the sake of
667 <       * consistency with cluster{} flags
668 <       */
669 <      *p++ = 'c';
670 <      flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
671 <
672 <      sendto_one(source_p, form_str(RPL_STATSULINE),
673 <                 me.name, source_p->name, conf->name,
674 <                 matchitem->user?matchitem->user: "*",
675 <                 matchitem->host?matchitem->host: "*", buf);
676 <    }
677 <
678 <    DLINK_FOREACH(ptr, cluster_items.head)
679 <    {
680 <      conf = ptr->data;
681 <
682 <      p = buf;
683 <
684 <      *p++ = 'C';
685 <      flags_to_ascii(conf->flags, shared_bit_table, p, 0);
686 <
687 <      sendto_one(source_p, form_str(RPL_STATSULINE),
688 <                 me.name, source_p->name, conf->name,
689 <                 "*", "*", buf);
690 <    }
691 <
692 <    break;
693 <
694 <  case OPER_TYPE:
695 <    DLINK_FOREACH(ptr, oconf_items.head)
696 <    {
697 <      conf = ptr->data;
698 <      aconf = map_to_conf(conf);
699 <
700 <      /* Don't allow non opers to see oper privs */
701 <      if (HasUMode(source_p, UMODE_OPER))
702 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
703 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
704 <                   conf->name, oper_privs_as_string(aconf->port),
705 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
706 <      else
707 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
708 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
709 <                   conf->name, "0",
710 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
711 <    }
712 <    break;
713 <
714 <  case CLASS_TYPE:
715 <    DLINK_FOREACH(ptr, class_items.head)
716 <    {
717 <      conf = ptr->data;
718 <      classitem = map_to_conf(conf);
719 <      sendto_one(source_p, form_str(RPL_STATSYLINE),
720 <                 me.name, source_p->name, 'Y',
721 <                 conf->name, PingFreq(classitem),
722 <                 ConFreq(classitem),
723 <                 MaxTotal(classitem), MaxSendq(classitem),
724 <                 CurrUserCount(classitem),
725 <                 classitem->active ? "active" : "disabled");
726 <    }
727 <    break;
728 <
729 <  case CONF_TYPE:
730 <  case CLIENT_TYPE:
731 <    break;
732 <
733 <  case SERVICE_TYPE:
734 <    DLINK_FOREACH(ptr, service_items.head)
735 <    {
736 <      conf = ptr->data;
737 <      sendto_one(source_p, form_str(RPL_STATSSERVICE),
738 <                 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
739 <    }
740 <    break;
741 <
742 <  case SERVER_TYPE:
743 <    DLINK_FOREACH(ptr, server_items.head)
744 <    {
745 <      p = buf;
746 <
747 <      conf = ptr->data;
748 <      aconf = map_to_conf(conf);
749 <
750 <      buf[0] = '\0';
751 <
752 <      if (IsConfAllowAutoConn(aconf))
753 <        *p++ = 'A';
754 <      if (IsConfCryptLink(aconf))
755 <        *p++ = 'C';
756 <      if (IsConfTopicBurst(aconf))
757 <        *p++ = 'T';
758 <      if (IsConfCompressed(aconf))
759 <        *p++ = 'Z';
760 <      if (buf[0] == '\0')
761 <        *p++ = '*';
762 <
763 <      *p = '\0';
764 <
765 <      /*
766 <       * Allow admins to see actual ips unless hide_server_ips is enabled
767 <       */
768 <      if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
769 <        sendto_one(source_p, form_str(RPL_STATSCLINE),
770 <                   me.name, source_p->name, 'C', aconf->host,
771 <                   buf, conf->name, aconf->port,
772 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
773 <        else
774 <          sendto_one(source_p, form_str(RPL_STATSCLINE),
775 <                     me.name, source_p->name, 'C',
776 <                     "*@127.0.0.1", buf, conf->name, aconf->port,
777 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
778 <    }
779 <    break;
780 <
781 <  case HUB_TYPE:
782 <    DLINK_FOREACH(ptr, hub_items.head)
783 <    {
784 <      conf = ptr->data;
785 <      matchitem = map_to_conf(conf);
786 <      sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
787 <                 source_p->name, 'H', matchitem->host, conf->name, 0, "*");
788 <    }
789 <    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 <    {
794 <      conf = ptr->data;
795 <      matchitem = map_to_conf(conf);
796 <      sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
797 <                 source_p->name, 'L', matchitem->host, conf->name, 0, "*");
798 <    }
799 <    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:
806 <  case NRESV_TYPE:
807 <  case CLUSTER_TYPE:
808 <  default:
809 <    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 823 | 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   {
829  struct Client *source_p = va_arg(args, struct Client *);
830  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)))
835 <    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,
860 <                "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
880 <       * capture reject code here or rely on the connecting too fast code.
881 <       * - Dianora
882 <       */
883 <      if (REJECT_HOLD_TIME > 0)
884 <      {
885 <        sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
886 <                   me.name, source_p->name);
887 <        source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
888 <        SetCaptured(source_p);
889 <      }
890 <      else
891 <        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 <     /*
896 <      * Don't exit them immediately, play with them a bit.
897 <      * - Dianora
898 <      */
899 <     if (REJECT_HOLD_TIME > 0)
900 <     {
901 <       source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
902 <       SetCaptured(source_p);
903 <     }
904 <     else
905 <       exit_client(source_p, &me, "Banned");
288 >     exit_client(source_p, "Banned");
289       ++ServerStats.is_ref;
290       break;
291  
# Line 911 | 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
920 *              - 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;
929 <  char non_ident[USERLEN + 1] = { '~', '\0' };
930 <  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;
949 <  uhi[1] = client_p->host;
950 <  uhi[2] = client_p->sockhost;
951 <
952 <  rkconf = find_regexp_kline(uhi);
953 <
954 <  if (aconf != NULL)
328 >  if (conf)
329    {
330 <    if (IsConfClient(aconf) && !rkconf)
330 >    if (IsConfClient(conf))
331      {
332 <      conf = unmap_conf_item(aconf);
959 <
960 <      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);
966 <        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))
978 <          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,
992 <                   client_p->name);
993 <      if (ConfigFileEntry.kline_with_reason)
994 <        sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
995 <                  me.name, client_p->name, aconf->reason);
996 <      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 1008 | 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;
1014 <  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);
1024 <  if (aconf->class_ptr == NULL)
1025 <    return NOT_AUTHORIZED;  /* If class is missing, this is best */
1026 <
1027 <  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 1033 | Line 395 | attach_iline(struct Client *client_p, st
395     * setting a_limit_reached if any limit is reached.
396     * - Dianora
397     */
398 <  if (MaxTotal(aclass) != 0 && CurrUserCount(aclass) >= MaxTotal(aclass))
398 >  if (class->max_total && class->ref_count >= class->max_total)
399      a_limit_reached = 1;
400 <  else if (MaxPerIp(aclass) != 0 && ip_found->count > MaxPerIp(aclass))
400 >  else if (class->max_perip && ip_found->count > class->max_perip)
401      a_limit_reached = 1;
402 <  else if (MaxLocal(aclass) != 0 && local >= MaxLocal(aclass))
402 >  else if (class->max_local && local >= class->max_local)
403      a_limit_reached = 1;
404 <  else if (MaxGlobal(aclass) != 0 && global >= MaxGlobal(aclass))
404 >  else if (class->max_global && global >= class->max_global)
405      a_limit_reached = 1;
406 <  else if (MaxIdent(aclass) != 0 && ident >= MaxIdent(aclass) &&
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, "
1055 <               "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 1068 | 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),
1072 <    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 1118 | 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 1169 | 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 1211 | 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 1223 | 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 1235 | Line 596 | void
596   count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
597   {
598    struct ip_entry *ptr;
1238  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 1262 | Line 622 | garbage_collect_ip_entries(void)
622    struct ip_entry *ptr;
623    struct ip_entry *last_ptr;
624    struct ip_entry *next_ptr;
1265  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 1279 | 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 1296 | 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;
1303 <  struct ConfItem *conf;
1304 <  struct ClassItem *aclass;
1305 <  struct AccessItem *aconf;
1306 <  struct ConfItem *aclass_conf;
1307 <  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;
1312 <
1313 <    if (type == CONF_TYPE || conf->type == type)
1314 <    {
1315 <      dlinkDelete(ptr, &client_p->localClient->confs);
1316 <      free_dlink_node(ptr);
665 >    struct MaskItem *conf = ptr->data;
666  
667 <      switch (conf->type)
668 <      {
669 <      case CLIENT_TYPE:
1321 <      case OPER_TYPE:
1322 <      case SERVER_TYPE:
1323 <        aconf = map_to_conf(conf);
1324 <
1325 <        assert(aconf->clients > 0);
1326 <
1327 <        if ((aclass_conf = ClassPtr(aconf)) != NULL)
1328 <        {
1329 <          aclass = map_to_conf(aclass_conf);
1330 <
1331 <          assert(aclass->curr_user_count > 0);
1332 <
1333 <          if (conf->type == CLIENT_TYPE)
1334 <            remove_from_cidr_check(&client_p->localClient->ip, aclass);
1335 <          if (--aclass->curr_user_count == 0 && aclass->active == 0)
1336 <            delete_conf_item(aclass_conf);
1337 <        }
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:
1346 <        match_item = map_to_conf(conf);
1347 <        if (match_item->ref_count == 0 && match_item->illegal)
1348 <          delete_conf_item(conf);
1349 <        break;
1350 <      default:
1351 <        break;
1352 <      }
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      }
1357  }
685  
686 <  return -1;
686 >    if (--conf->ref_count == 0 && conf->active == 0)
687 >      conf_free(conf);
688 >  }
689   }
690  
691   /* attach_conf()
# Line 1370 | 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 <  {
1382 <    struct AccessItem *aconf = map_to_conf(conf);
1383 <    struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1384 <
1385 <    if (IsConfIllegal(aconf))
1386 <      return NOT_AUTHORIZED;
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 <    if (conf->type == CLIENT_TYPE)
713 <      if (cidr_limit_reached(IsConfExemptLimits(aconf),
1390 <                             &client_p->localClient->ip, aclass))
1391 <        return TOO_MANY;    /* Already at maximum allowed */
1392 <
1393 <    CurrUserCount(aclass)++;
1394 <    aconf->clients++;
1395 <  }
1396 <  else if (conf->type == HUB_TYPE || conf->type == LEAF_TYPE)
1397 <  {
1398 <    struct MatchItem *match_item = map_to_conf(conf);
1399 <    match_item->ref_count++;
1400 <  }
712 >  conf->class->ref_count++;
713 >  conf->ref_count++;
714  
715    dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
716  
# Line 1417 | Line 730 | attach_connect_block(struct Client *clie
730                       const char *host)
731   {
732    dlink_node *ptr;
733 <  struct ConfItem *conf;
1421 <  struct AccessItem *aconf;
733 >  struct MaskItem *conf = NULL;
734  
735    assert(client_p != NULL);
736    assert(host != NULL);
# Line 1429 | Line 741 | attach_connect_block(struct Client *clie
741    DLINK_FOREACH(ptr, server_items.head)
742    {
743      conf = ptr->data;
1432    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 1441 | Line 752 | attach_connect_block(struct Client *clie
752    return 0;
753   }
754  
1444 /* find_conf_exact()
1445 *
1446 * inputs       - type of ConfItem
1447 *              - pointer to name to find
1448 *              - pointer to username to find
1449 *              - pointer to host to find
1450 * output       - NULL or pointer to conf found
1451 * side effects - find a conf entry which matches the hostname
1452 *                and has the same name.
1453 */
1454 struct ConfItem *
1455 find_conf_exact(ConfType type, const char *name, const char *user,
1456                const char *host)
1457 {
1458  dlink_node *ptr;
1459  dlink_list *list_p;
1460  struct ConfItem *conf = NULL;
1461  struct AccessItem *aconf;
1462
1463  /* Only valid for OPER_TYPE and ...? */
1464  list_p = map_to_list(type);
1465
1466  DLINK_FOREACH(ptr, (*list_p).head)
1467  {
1468    conf = ptr->data;
1469
1470    if (conf->name == NULL)
1471      continue;
1472    aconf = map_to_conf(conf);
1473    if (aconf->host == NULL)
1474      continue;
1475    if (irccmp(conf->name, name) != 0)
1476      continue;
1477
1478    /*
1479    ** Accept if the *real* hostname (usually sockethost)
1480    ** socket host) matches *either* host or name field
1481    ** of the configuration.
1482    */
1483    if (!match(aconf->host, host) || !match(aconf->user, user))
1484      continue;
1485    if (type == OPER_TYPE)
1486    {
1487      struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1488
1489      if (aconf->clients >= MaxTotal(aclass))
1490        continue;
1491    }
1492
1493    return conf;
1494  }
1495
1496  return NULL;
1497 }
1498
755   /* find_conf_name()
756   *
757   * inputs       - pointer to conf link list to search
# Line 1505 | 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 1533 | 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:
1541 <    return(&rxconf_items);
1542 <    break;
1543 <  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:
1556 <    return(&class_items);
1557 <    break;
1558 <  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;
1567  case CONF_TYPE:
1568  case GLINE_TYPE:
1569  case KLINE_TYPE:
1570  case DLINE_TYPE:
1571  case CRESV_TYPE:
819    default:
820      return NULL;
821    }
# Line 1580 | 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;
1593 <  struct AccessItem *aconf=NULL;
1594 <  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
1600 <  case RXLINE_TYPE:
1601 <      DLINK_FOREACH(ptr, list_p->head)
1602 <      {
1603 <        conf = ptr->data;
1604 <        assert(conf->regexpname);
1605 <
1606 <        if (!ircd_pcre_exec(conf->regexpname, name))
1607 <          return conf;
1608 <      }
1609 <      break;
1610 < #endif
1611 <  case SERVICE_TYPE:
844 >  case CONF_SERVICE:
845      DLINK_FOREACH(ptr, list_p->head)
846      {
847        conf = ptr->data;
# Line 1620 | 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  
1630      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;
1651      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 1669 | 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 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;
1682 <  struct MatchItem *match_item;
1683 <  dlink_list *list_p;
1684 <
1685 <  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;
945 <      aconf = (struct AccessItem *)map_to_conf(conf);
945 >
946        if (EmptyString(conf->name))
947 <        continue;
948 <    
949 <      if (irccmp(conf->name, name) == 0)
947 >        continue;
948 >
949 >      if (!irccmp(conf->name, name))
950        {
951 <        if ((user == NULL && (host == NULL)))
952 <          return (conf);
953 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
954 <          return (conf);
955 <        if (match(aconf->user, user) && match(aconf->host, host))
956 <          return (conf);
951 >        if (!who)
952 >          return conf;
953 >        if (EmptyString(conf->user) || EmptyString(conf->host))
954 >          return NULL;
955 >        if (!match(conf->user, who->username))
956 >        {
957 >          switch (conf->htype)
958 >          {
959 >            case HM_HOST:
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, &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, &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:
979 >              assert(0);
980 >          }
981 >        }
982        }
983      }
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 <      {
1750 <          return (conf);
1751 <      }
1003 >        return conf;
1004      }
1753    break;
1005  
1755  case CLASS_TYPE:
1756    DLINK_FOREACH(ptr, list_p->head)
1757    {
1758      conf = ptr->data;
1759      if (EmptyString(conf->name))
1760        continue;
1761    
1762      if (irccmp(conf->name, name) == 0)
1763        return (conf);
1764    }
1006      break;
1007  
1008    default:
1009      break;
1010    }
1011 <  return(NULL);
1011 >
1012 >  return NULL;
1013   }
1014  
1015   /* rehash()
# Line 1779 | 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 1792 | 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();
1801 <
1802 <  rehashed_klines = 1;
1803 < /* XXX */
1804 <  if (ConfigLoggingEntry.use_logging)
1805 <    log_close_all();
1806 <
1807 <  return(0);
1043 >  return 0;
1044   }
1045  
1046   /* set_default_conf()
# Line 1822 | 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 1832 | 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 1841 | Line 1078 | set_default_conf(void)
1078    ServerInfo.specific_ipv6_vhost = 0;
1079  
1080    ServerInfo.max_clients = MAXCLIENTS_MAX;
1081 <
1081 >  ServerInfo.max_nick_length = 9;
1082 >  ServerInfo.max_topic_length = 80;
1083    ServerInfo.hub = 0;
1084    ServerInfo.dns_host.sin_addr.s_addr = 0;
1085    ServerInfo.dns_host.sin_port = 0;
1086 +
1087    AdminInfo.name = NULL;
1088    AdminInfo.email = NULL;
1089    AdminInfo.description = NULL;
1090  
1091 <  log_close_all();
1091 >  log_del_all();
1092  
1093    ConfigLoggingEntry.use_logging = 1;
1855  ConfigLoggingEntry.timestamp = 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;
1862 <  ConfigChannel.use_knock = 1;
1863 <  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;
1866 <  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;
1872  ConfigChannel.burst_topicwho = 1;
1107  
1108    ConfigServerHide.flatten_links = 0;
1109    ConfigServerHide.links_delay = 300;
1110    ConfigServerHide.hidden = 0;
1877  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 <  
1118 <  DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1117 >  ConfigFileEntry.away_count = 2;
1118 >  ConfigFileEntry.away_time = 10;
1119 >  ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1120    ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1121 +  ConfigFileEntry.cycle_on_host_change = 1;
1122 +  ConfigFileEntry.glines = 0;
1123 +  ConfigFileEntry.gline_time = 12 * 3600;
1124 +  ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
1125    ConfigFileEntry.gline_min_cidr = 16;
1126    ConfigFileEntry.gline_min_cidr6 = 48;
1127    ConfigFileEntry.invisible_on_connect = 1;
1888  ConfigFileEntry.burst_away = 0;
1889  ConfigFileEntry.use_whois_actually = 1;
1128    ConfigFileEntry.tkline_expire_notices = 1;
1129    ConfigFileEntry.hide_spoof_ips = 1;
1130    ConfigFileEntry.ignore_bogus_ts = 0;
1131    ConfigFileEntry.disable_auth = 0;
1894  ConfigFileEntry.disable_remote = 0;
1132    ConfigFileEntry.kill_chase_time_limit = 90;
1133    ConfigFileEntry.default_floodcount = 8;
1134    ConfigFileEntry.failed_oper_notice = 1;
# Line 1905 | Line 1142 | set_default_conf(void)
1142    ConfigFileEntry.anti_spam_exit_message_time = 0;
1143    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1144    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1145 <  ConfigFileEntry.kline_with_reason = 1;
1146 <  ConfigFileEntry.kline_reason = NULL;
1910 <  ConfigFileEntry.warn_no_nline = 1;
1145 >  ConfigFileEntry.warn_no_connect_block = 1;
1146 >  ConfigFileEntry.stats_e_disabled = 0;
1147    ConfigFileEntry.stats_o_oper_only = 0;
1148 <  ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
1149 <  ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
1148 >  ConfigFileEntry.stats_k_oper_only = 1;  /* 1 = masked */
1149 >  ConfigFileEntry.stats_i_oper_only = 1;  /* 1 = masked */
1150    ConfigFileEntry.stats_P_oper_only = 0;
1151 +  ConfigFileEntry.stats_u_oper_only = 0;
1152    ConfigFileEntry.caller_id_wait = 60;
1153    ConfigFileEntry.opers_bypass_callerid = 0;
1154    ConfigFileEntry.pace_wait = 10;
# Line 1921 | Line 1158 | set_default_conf(void)
1158    ConfigFileEntry.no_oper_flood = 0;
1159    ConfigFileEntry.true_no_oper_flood = 0;
1160    ConfigFileEntry.oper_pass_resv = 1;
1924  ConfigFileEntry.glines = 0;
1925  ConfigFileEntry.gline_time = 12 * 3600;
1161    ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1927  ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1162    ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1163 <  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1164 <    UMODE_OPERWALL | UMODE_WALLOP;
1165 <  DupString(ConfigFileEntry.servlink_path, SLPATH);
1932 < #ifdef HAVE_LIBCRYPTO
1933 <  /* jdc -- This is our default value for a cipher.  According to the
1934 <   *        CRYPTLINK document (doc/cryptlink.txt), BF/128 must be supported
1935 <   *        under all circumstances if cryptlinks are enabled.  So,
1936 <   *        this will be our default.
1937 <   *
1938 <   *        NOTE: I apologise for the hard-coded value of "1" (BF/128).
1939 <   *              This should be moved into a find_cipher() routine.
1940 <   */
1941 <  ConfigFileEntry.default_cipher_preference = &CipherTable[1];
1942 < #endif
1943 <  ConfigFileEntry.use_egd = 0;
1944 <  ConfigFileEntry.egdpool_path = NULL;
1945 < #ifdef HAVE_LIBZ
1946 <  ConfigFileEntry.compression_level = 0;
1947 < #endif
1948 <  ConfigFileEntry.throttle_time = 10;
1949 < }
1950 <
1951 < /* read_conf()
1952 < *
1953 < * inputs       - file descriptor pointing to config file to use
1954 < * output       - None
1955 < * side effects - Read configuration file.
1956 < */
1957 < static void
1958 < read_conf(FBFILE *file)
1959 < {
1960 <  lineno = 0;
1961 <
1962 <  set_default_conf(); /* Set default values prior to conf parsing */
1963 <  conf_parser_ctx.pass = 1;
1964 <  yyparse();          /* pick up the classes first */
1965 <
1966 <  fbrewind(file);
1967 <
1968 <  conf_parser_ctx.pass = 2;
1969 <  yyparse();          /* Load the values from the conf */
1970 <  validate_conf();    /* Check to make sure some values are still okay. */
1971 <                      /* Some global values are also loaded here. */
1972 <  check_class();      /* Make sure classes are valid */
1163 >  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE | UMODE_WALLOP;
1164 >  ConfigFileEntry.throttle_count = 1;
1165 >  ConfigFileEntry.throttle_time = 1;
1166   }
1167  
1168   static void
# Line 1981 | Line 1174 | validate_conf(void)
1174    if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1175      ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1176  
1984  if (ConfigFileEntry.servlink_path == NULL)
1985    DupString(ConfigFileEntry.servlink_path, SLPATH);
1986
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);
1995 <
1996 <  if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1997 <      (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1998 <    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 < /* lookup_confhost()
1189 > /* read_conf()
1190   *
1191 < * start DNS lookups of all hostnames in the conf
1192 < * line and convert an IP addresses in a.b.c.d number for to IP#s.
1191 > * inputs       - file descriptor pointing to config file to use
1192 > * output       - None
1193 > * side effects - Read configuration file.
1194   */
1195   static void
1196 < lookup_confhost(struct ConfItem *conf)
1196 > read_conf(FILE *file)
1197   {
1198 <  struct AccessItem *aconf;
2012 <  struct addrinfo hints, *res;
1198 >  lineno = 0;
1199  
1200 <  aconf = map_to_conf(conf);
1200 >  set_default_conf();  /* Set default values prior to conf parsing */
1201 >  conf_parser_ctx.pass = 1;
1202 >  yyparse();  /* Pick up the classes first */
1203  
1204 <  if (EmptyString(aconf->host) ||
2017 <      EmptyString(aconf->user))
2018 <  {
2019 <    ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
2020 <         aconf->host, conf->name);
2021 <    return;
2022 <  }
1204 >  rewind(file);
1205  
1206 <  if (strchr(aconf->host, '*') ||
1207 <      strchr(aconf->host, '?'))
1208 <    return;
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 >  class_delete_marked();  /* Delete unused classes that are marked for deletion */
1211 > }
1212  
1213 <  /* Do name lookup now on hostnames given and store the
1213 > /* lookup_confhost()
1214 > *
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 > void
1219 > lookup_confhost(struct MaskItem *conf)
1220 > {
1221 >  struct addrinfo hints, *res;
1222 >
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 2036 | 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  
2047  memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
2048  aconf->ipnum.ss_len = res->ai_addrlen;
2049  aconf->ipnum.ss.ss_family = res->ai_family;
1247    freeaddrinfo(res);
1248   }
1249  
# Line 2060 | 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) <
2076 <      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  
2086 static struct AccessItem *
2087 find_regexp_kline(const char *uhi[])
2088 {
2089 #ifdef HAVE_LIBPCRE
2090  const dlink_node *ptr = NULL;
2091
2092  DLINK_FOREACH(ptr, rkconf_items.head)
2093  {
2094    struct AccessItem *aptr = map_to_conf(ptr->data);
2095
2096    assert(aptr->regexuser);
2097    assert(aptr->regexhost);
2098
2099    if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2100        (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2101         !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2102      return aptr;
2103  }
2104 #endif
2105  return NULL;
2106 }
2107
2108 /* find_kill()
2109 *
2110 * inputs       - pointer to client structure
2111 * output       - pointer to struct AccessItem if found
2112 * side effects - See if this user is klined already,
2113 *                and if so, return struct AccessItem pointer
2114 */
2115 struct AccessItem *
2116 find_kill(struct Client *client_p)
2117 {
2118  struct AccessItem *aconf = NULL;
2119  const char *uhi[3];
2120
2121  uhi[0] = client_p->username;
2122  uhi[1] = client_p->host;
2123  uhi[2] = client_p->sockhost;
2124
2125  assert(client_p != NULL);
2126
2127  aconf = find_kline_conf(client_p->host, client_p->username,
2128                          &client_p->localClient->ip,
2129                          client_p->localClient->aftype);
2130  if (aconf == NULL)
2131    aconf = find_regexp_kline(uhi);
2132
2133  if (aconf && (aconf->status & CONF_KLINE))
2134    return aconf;
2135
2136  return NULL;
2137 }
2138
2139 struct AccessItem *
2140 find_gline(struct Client *client_p)
2141 {
2142  struct AccessItem *aconf;
2143
2144  assert(client_p != NULL);
2145
2146  aconf = find_gline_conf(client_p->host, client_p->username,
2147                          &client_p->localClient->ip,
2148                          client_p->localClient->aftype);
2149
2150  if (aconf && (aconf->status & CONF_GLINE))
2151    return aconf;
2152
2153  return NULL;
2154 }
2155
2156 /* add_temp_line()
2157 *
2158 * inputs        - pointer to struct ConfItem
2159 * output        - none
2160 * Side effects  - links in given struct ConfItem into
2161 *                 temporary *line link list
2162 */
2163 void
2164 add_temp_line(struct ConfItem *conf)
2165 {
2166  struct AccessItem *aconf;
2167
2168  if (conf->type == DLINE_TYPE)
2169  {
2170    aconf = map_to_conf(conf);
2171    SetConfTemporary(aconf);
2172    dlinkAdd(conf, &conf->node, &temporary_dlines);
2173    MyFree(aconf->user);
2174    aconf->user = NULL;
2175    add_conf_by_address(CONF_DLINE, aconf);
2176  }
2177  else if (conf->type == KLINE_TYPE)
2178  {
2179    aconf = map_to_conf(conf);
2180    SetConfTemporary(aconf);
2181    dlinkAdd(conf, &conf->node, &temporary_klines);
2182    add_conf_by_address(CONF_KILL, aconf);
2183  }
2184  else if (conf->type == GLINE_TYPE)
2185  {
2186    aconf = map_to_conf(conf);
2187    SetConfTemporary(aconf);
2188    dlinkAdd(conf, &conf->node, &temporary_glines);
2189    add_conf_by_address(CONF_GLINE, aconf);
2190  }
2191  else if (conf->type == XLINE_TYPE)
2192  {
2193    conf->flags |= CONF_FLAGS_TEMPORARY;
2194    dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2195  }
2196  else if (conf->type == RXLINE_TYPE)
2197  {
2198    conf->flags |= CONF_FLAGS_TEMPORARY;
2199    dlinkAdd(conf, make_dlink_node(), &temporary_rxlines);
2200  }
2201  else if (conf->type == RKLINE_TYPE)
2202  {
2203    conf->flags |= CONF_FLAGS_TEMPORARY;
2204    dlinkAdd(conf, make_dlink_node(), &temporary_rklines);
2205  }
2206  else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2207  {
2208    conf->flags |= CONF_FLAGS_TEMPORARY;
2209    dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2210  }
2211 }
2212
1286   /* cleanup_tklines()
1287   *
1288   * inputs       - NONE
# Line 2220 | Line 1293 | add_temp_line(struct ConfItem *conf)
1293   void
1294   cleanup_tklines(void *notused)
1295   {
1296 <  expire_tklines(&temporary_glines);
1297 <  expire_tklines(&temporary_klines);
1298 <  expire_tklines(&temporary_dlines);
1299 <  expire_tklines(&temporary_xlines);
2227 <  expire_tklines(&temporary_rxlines);
2228 <  expire_tklines(&temporary_rklines);
2229 <  expire_tklines(&temporary_resv);
1296 >  hostmask_expire_temporary();
1297 >  expire_tklines(&xconf_items);
1298 >  expire_tklines(&nresv_items);
1299 >  expire_tklines(&cresv_items);
1300   }
1301  
1302   /* expire_tklines()
# Line 2238 | 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;
2243 <  struct ConfItem *conf;
2244 <  struct MatchItem *xconf;
2245 <  struct MatchItem *nconf;
2246 <  struct AccessItem *aconf;
2247 <  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;
2252    if (conf->type == GLINE_TYPE ||
2253        conf->type == KLINE_TYPE ||
2254        conf->type == DLINE_TYPE)
2255    {
2256      aconf = (struct AccessItem *)map_to_conf(conf);
2257      if (aconf->hold <= CurrentTime)
2258      {
2259        /* XXX - Do we want GLINE expiry notices?? */
2260        /* Alert opers that a TKline expired - Hwy */
2261        if (ConfigFileEntry.tkline_expire_notices)
2262        {
2263          if (aconf->status & CONF_KILL)
2264          {
2265            sendto_realops_flags(UMODE_ALL, L_ALL,
2266                                 "Temporary K-line for [%s@%s] expired",
2267                                 (aconf->user) ? aconf->user : "*",
2268                                 (aconf->host) ? aconf->host : "*");
2269          }
2270          else if (conf->type == DLINE_TYPE)
2271          {
2272            sendto_realops_flags(UMODE_ALL, L_ALL,
2273                                 "Temporary D-line for [%s] expired",
2274                                 (aconf->host) ? aconf->host : "*");
2275          }
2276        }
1317  
1318 <        dlinkDelete(ptr, tklist);
1319 <        delete_one_address_conf(aconf->host, aconf);
1320 <      }
1321 <    }
2282 <    else if (conf->type == XLINE_TYPE ||
2283 <             conf->type == RXLINE_TYPE)
2284 <    {
2285 <      xconf = (struct MatchItem *)map_to_conf(conf);
2286 <      if (xconf->hold <= CurrentTime)
2287 <      {
2288 <        if (ConfigFileEntry.tkline_expire_notices)
2289 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2290 <                               "Temporary X-line for [%s] %sexpired", conf->name,
2291 <                               conf->type == RXLINE_TYPE ? "(REGEX) " : "");
2292 <        dlinkDelete(ptr, tklist);
2293 <        free_dlink_node(ptr);
2294 <        delete_conf_item(conf);
2295 <      }
2296 <    }
2297 <    else if (conf->type == RKLINE_TYPE)
1318 >    if (!conf->until || conf->until > CurrentTime)
1319 >      continue;
1320 >
1321 >    if (conf->type == CONF_XLINE)
1322      {
1323 <      aconf = map_to_conf(conf);
1324 <      if (aconf->hold <= CurrentTime)
1325 <      {
1326 <        if (ConfigFileEntry.tkline_expire_notices)
2303 <           sendto_realops_flags(UMODE_ALL, L_ALL,
2304 <                                "Temporary K-line for [%s@%s] (REGEX) expired",
2305 <                                (aconf->user) ? aconf->user : "*",
2306 <                                (aconf->host) ? aconf->host : "*");
2307 <        dlinkDelete(ptr, tklist);
2308 <        free_dlink_node(ptr);
2309 <        delete_conf_item(conf);
2310 <      }
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)
2316 <      {
2317 <        if (ConfigFileEntry.tkline_expire_notices)
2318 <          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);
2321 <        free_dlink_node(ptr);
2322 <        delete_conf_item(conf);
2323 <      }
2324 <    }
2325 <    else if (conf->type == CRESV_TYPE)
2326 <    {
2327 <      cconf = (struct ResvChannel *)map_to_conf(conf);
2328 <      if (cconf->hold <= CurrentTime)
2329 <      {
2330 <        if (ConfigFileEntry.tkline_expire_notices)
2331 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2332 <                               "Temporary RESV for [%s] expired", cconf->name);
2333 <        delete_channel_resv(cconf);
2334 <      }
1333 >      conf_free(conf);
1334      }
1335    }
1336   }
# Line 2344 | Line 1343 | expire_tklines(dlink_list *tklist)
1343   */
1344   static const struct oper_privs
1345   {
1346 <  const unsigned int oprivs;
2348 <  const unsigned int hidden;
1346 >  const unsigned int flag;
1347    const unsigned char c;
1348   } flag_list[] = {
1349 <  { OPER_FLAG_ADMIN,       OPER_FLAG_HIDDEN_ADMIN,  'A' },
1350 <  { OPER_FLAG_REMOTEBAN,   0,                       'B' },
1351 <  { OPER_FLAG_DIE,         0,                       'D' },
1352 <  { OPER_FLAG_GLINE,       0,                       'G' },
1353 <  { OPER_FLAG_REHASH,      0,                       'H' },
1354 <  { OPER_FLAG_K,           0,                       'K' },
1355 <  { OPER_FLAG_OPERWALL,    0,                       'L' },
1356 <  { OPER_FLAG_N,           0,                       'N' },
1357 <  { OPER_FLAG_GLOBAL_KILL, 0,                       'O' },
1358 <  { OPER_FLAG_REMOTE,      0,                       'R' },
1359 <  { OPER_FLAG_OPER_SPY,    0,                       'S' },
1360 <  { OPER_FLAG_UNKLINE,     0,                       'U' },
1361 <  { OPER_FLAG_X,           0,                       'X' },
1362 <  { 0, 0, '\0' }
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;
2372  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 <        (port & flag_list[i].hidden) == 0)
2378 <      *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 2386 | Line 1383 | oper_privs_as_string(const unsigned int
1383   }
1384  
1385   /*
1386 < * Input: A client to find the active oper{} name for.
1386 > * Input: A client to find the active operator {} name for.
1387   * Output: The nick!user@host{oper} of the oper.
1388   *         "oper" is server name for remote opers
1389   * Side effects: None.
1390   */
1391 < char *
1391 > const char *
1392   get_oper_name(const struct Client *client_p)
1393   {
1394 <  dlink_node *cnode;
2398 <  struct ConfItem *conf;
2399 <  struct AccessItem *aconf;
2400 <
1394 >  const dlink_node *cnode = NULL;
1395    /* +5 for !,@,{,} and null */
1396    static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
1397  
1398    if (MyConnect(client_p))
1399    {
1400 <    DLINK_FOREACH(cnode, client_p->localClient->confs.head)
1400 >    if ((cnode = client_p->localClient->confs.head))
1401      {
1402 <      conf = cnode->data;
2409 <      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
1413 <     * with no oper{} conf attached, it would be good for us to know...
1412 >    /*
1413 >     * Probably should assert here for now. If there is an oper out there
1414 >     * with no operator {} conf attached, it would be good for us to know...
1415       */
1416 <    assert(0); /* Oper without oper conf! */
1416 >    assert(0);  /* Oper without oper conf! */
1417    }
1418  
1419    snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1420 <           client_p->username, client_p->host, client_p->servptr->name);
1420 >           client_p->username, client_p->host, client_p->servptr->name);
1421    return buffer;
1422   }
1423  
# Line 2436 | Line 1430 | get_oper_name(const struct Client *clien
1430   void
1431   read_conf_files(int cold)
1432   {
1433 <  const char *filename;
1434 <  char chanmodes[32];
1435 <  char chanlimit[32];
1433 >  const char *filename = NULL;
1434 >  char chanmodes[IRCD_BUFSIZE] = "";
1435 >  char chanlimit[IRCD_BUFSIZE] = "";
1436  
1437    conf_parser_ctx.boot = cold;
1438 <  filename = get_conf_name(CONF_TYPE);
1438 >  filename = ConfigFileEntry.configfile;
1439  
1440    /* We need to know the initial filename for the yyerror() to report
1441       FIXME: The full path is in conffilenamebuf first time since we
1442 <             dont know anything else
1442 >             don't know anything else
1443  
1444 <     - Gozem 2002-07-21
1444 >     - Gozem 2002-07-21
1445    */
1446    strlcpy(conffilebuf, filename, sizeof(conffilebuf));
1447  
1448 <  if ((conf_parser_ctx.conf_file = fbopen(filename, "r")) == NULL)
1448 >  if ((conf_parser_ctx.conf_file = fopen(filename, "r")) == NULL)
1449    {
1450      if (cold)
1451      {
# Line 2461 | Line 1455 | read_conf_files(int cold)
1455      }
1456      else
1457      {
1458 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1459 <                           "Unable to read configuration file '%s': %s",
1460 <                           filename, strerror(errno));
1458 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1459 >                           "Unable to read configuration file '%s': %s",
1460 >                           filename, strerror(errno));
1461        return;
1462      }
1463    }
# Line 2472 | Line 1466 | read_conf_files(int cold)
1466      clear_out_old_conf();
1467  
1468    read_conf(conf_parser_ctx.conf_file);
1469 <  fbclose(conf_parser_ctx.conf_file);
1469 >  fclose(conf_parser_ctx.conf_file);
1470  
1471 +  log_reopen_all();
1472 +
1473 +  add_isupport("NICKLEN", NULL, ServerInfo.max_nick_length);
1474    add_isupport("NETWORK", ServerInfo.network_name, -1);
1475 <  snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
1476 <           ConfigChannel.use_except ? "e" : "",
2480 <           ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
1475 >
1476 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1477    add_isupport("MAXLIST", chanmodes, -1);
1478    add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1479 +  add_isupport("CHANTYPES", "#", -1);
1480  
1481 <  if (ConfigChannel.disable_local_channels)
1482 <    add_isupport("CHANTYPES", "#", -1);
2486 <  else
2487 <    add_isupport("CHANTYPES", "#&", -1);
2488 <
2489 <  snprintf(chanlimit, sizeof(chanlimit), "%s:%d",
2490 <           ConfigChannel.disable_local_channels ? "#" : "#&",
2491 <           ConfigChannel.max_chans_per_user);
1481 >  snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1482 >           ConfigChannel.max_channels);
1483    add_isupport("CHANLIMIT", chanlimit, -1);
1484 <  snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
1485 <           ConfigChannel.use_except ? "e" : "",
1486 <           ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
2496 <  add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2497 <
2498 <  if (ConfigChannel.use_except)
2499 <    add_isupport("EXCEPTS", "e", -1);
2500 <  if (ConfigChannel.use_invex)
2501 <    add_isupport("INVEX", "I", -1);
1484 >  snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,cimnprstMORS");
1485 >  add_isupport("CHANNELLEN", NULL, CHANNELLEN);
1486 >  add_isupport("TOPICLEN", NULL, ServerInfo.max_topic_length);
1487    add_isupport("CHANMODES", chanmodes, -1);
1488  
1489    /*
# Line 2506 | Line 1491 | read_conf_files(int cold)
1491     * on strlen(form_str(RPL_ISUPPORT))
1492     */
1493    rebuild_isupport_message_line();
2509
2510 #ifdef HAVE_LIBPCRE
2511  parse_conf_file(RKLINE_TYPE, cold);
2512  parse_conf_file(RXLINE_TYPE, cold);
2513 #endif
2514  parse_conf_file(KLINE_TYPE, cold);
2515  parse_conf_file(DLINE_TYPE, cold);
2516  parse_conf_file(XLINE_TYPE, cold);
2517  parse_conf_file(NRESV_TYPE, cold);
2518  parse_conf_file(CRESV_TYPE, cold);
2519 }
2520
2521 /* parse_conf_file()
2522 *
2523 * inputs       - type of conf file to parse
2524 * output       - none
2525 * side effects - conf file for givenconf type is opened and read then parsed
2526 */
2527 static void
2528 parse_conf_file(int type, int cold)
2529 {
2530  FBFILE *file = NULL;
2531  const char *filename = get_conf_name(type);
2532
2533  if ((file = fbopen(filename, "r")) == NULL)
2534  {
2535    if (cold)
2536      ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2537           filename, strerror(errno));
2538    else
2539      sendto_realops_flags(UMODE_ALL, L_ALL,
2540                    "Unable to read configuration file '%s': %s",
2541                           filename, strerror(errno));
2542  }
2543  else
2544  {
2545    parse_csv_file(file, type);
2546    fbclose(file);
2547  }
1494   }
1495  
1496   /* clear_out_old_conf()
# Line 2557 | Line 1503 | static void
1503   clear_out_old_conf(void)
1504   {
1505    dlink_node *ptr = NULL, *next_ptr = NULL;
1506 <  struct ConfItem *conf;
2561 <  struct AccessItem *aconf;
2562 <  struct ClassItem *cltmp;
2563 <  struct MatchItem *match_item;
1506 >  struct MaskItem *conf;
1507    dlink_list *free_items [] = {
1508 <    &server_items,   &oconf_items,    &hub_items, &leaf_items,
1509 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1510 <     &nresv_items, &cluster_items,  &gdeny_items, &service_items, NULL
1508 >    &server_items,   &oconf_items,
1509 >     &uconf_items,   &xconf_items,
1510 >     &nresv_items, &cluster_items,  &service_items, &cresv_items, NULL
1511    };
1512  
1513    dlink_list ** iterator = free_items; /* C is dumb */
# Line 2572 | Line 1515 | clear_out_old_conf(void)
1515    /* We only need to free anything allocated by yyparse() here.
1516     * Resetting structs, etc, is taken care of by set_default_conf().
1517     */
1518 <  
1518 >
1519    for (; *iterator != NULL; iterator++)
1520    {
1521      DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1522      {
1523        conf = ptr->data;
2581      /* XXX This is less than pretty */
2582      if (conf->type == SERVER_TYPE)
2583      {
2584        aconf = map_to_conf(conf);
1524  
1525 <        if (aconf->clients != 0)
2587 <        {
2588 <          SetConfIllegal(aconf);
2589 <          dlinkDelete(&conf->node, &server_items);
2590 <        }
2591 <        else
2592 <        {
2593 <          delete_conf_item(conf);
2594 <        }
2595 <      }
2596 <      else if (conf->type == OPER_TYPE)
2597 <      {
2598 <        aconf = map_to_conf(conf);
1525 >      dlinkDelete(&conf->node, map_to_list(conf->type));
1526  
1527 <        if (aconf->clients != 0)
1528 <        {
2602 <          SetConfIllegal(aconf);
2603 <          dlinkDelete(&conf->node, &oconf_items);
2604 <        }
2605 <        else
2606 <        {
2607 <          delete_conf_item(conf);
2608 <        }
2609 <      }
2610 <      else if (conf->type == CLIENT_TYPE)
1527 >      /* XXX This is less than pretty */
1528 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1529        {
1530 <        aconf = map_to_conf(conf);
1531 <
2614 <        if (aconf->clients != 0)
2615 <        {
2616 <          SetConfIllegal(aconf);
2617 <        }
2618 <        else
2619 <        {
2620 <          delete_conf_item(conf);
2621 <        }
1530 >        if (!conf->ref_count)
1531 >          conf_free(conf);
1532        }
1533 <      else if (conf->type == XLINE_TYPE  ||
2624 <               conf->type == RXLINE_TYPE ||
2625 <               conf->type == RKLINE_TYPE)
1533 >      else if (conf->type == CONF_XLINE)
1534        {
1535 <        /* temporary (r)xlines are also on
1536 <         * the (r)xconf items list */
2629 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2630 <          continue;
2631 <
2632 <        delete_conf_item(conf);
1535 >        if (!conf->until)
1536 >          conf_free(conf);
1537        }
1538        else
1539 <      {
2636 <        if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2637 <        {
2638 <          match_item = map_to_conf(conf);
2639 <          if (match_item->ref_count <= 0)
2640 <            delete_conf_item(conf);
2641 <          else
2642 <          {
2643 <            match_item->illegal = 1;
2644 <            dlinkDelete(&conf->node, *iterator);
2645 <          }
2646 <        }
2647 <        else
2648 <          delete_conf_item(conf);
2649 <      }
1539 >        conf_free(conf);
1540      }
1541    }
1542  
1543 +  motd_clear();
1544 +
1545    /*
1546     * don't delete the class table, rather mark all entries
1547 <   * for deletion. The table is cleaned up by check_class. - avalon
1547 >   * for deletion. The table is cleaned up by class_delete_marked. - avalon
1548     */
1549 <  DLINK_FOREACH(ptr, class_items.head)
2658 <  {
2659 <    cltmp = map_to_conf(ptr->data);
2660 <
2661 <    if (ptr != class_items.tail)  /* never mark the "default" class */
2662 <      cltmp->active = 0;
2663 <  }
1549 >  class_mark_for_deletion();
1550  
1551    clear_out_address_conf();
1552  
# Line 2674 | Line 1560 | clear_out_old_conf(void)
1560    ServerInfo.network_name = NULL;
1561    MyFree(ServerInfo.network_desc);
1562    ServerInfo.network_desc = NULL;
2677  MyFree(ConfigFileEntry.egdpool_path);
2678  ConfigFileEntry.egdpool_path = NULL;
1563   #ifdef HAVE_LIBCRYPTO
1564 <  if (ServerInfo.rsa_private_key != NULL)
1564 >  if (ServerInfo.rsa_private_key)
1565    {
1566      RSA_free(ServerInfo.rsa_private_key);
1567      ServerInfo.rsa_private_key = NULL;
# Line 2687 | Line 1571 | clear_out_old_conf(void)
1571    ServerInfo.rsa_private_key_file = NULL;
1572   #endif
1573  
2690  /* clean out old resvs from the conf */
2691  clear_conf_resv();
2692
1574    /* clean out AdminInfo */
1575    MyFree(AdminInfo.name);
1576    AdminInfo.name = NULL;
# Line 2698 | Line 1579 | clear_out_old_conf(void)
1579    MyFree(AdminInfo.description);
1580    AdminInfo.description = NULL;
1581  
2701  /* operator{} and class{} blocks are freed above */
1582    /* clean out listeners */
1583    close_listeners();
1584  
2705  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2706   * exempt{} and gecos{} blocks are freed above too
2707   */
2708
1585    /* clean out general */
1586    MyFree(ConfigFileEntry.service_name);
1587    ConfigFileEntry.service_name = NULL;
2712
2713  MyFree(ConfigFileEntry.servlink_path);
2714  ConfigFileEntry.servlink_path = NULL;
2715 #ifdef HAVE_LIBCRYPTO
2716  ConfigFileEntry.default_cipher_preference = NULL;
2717 #endif /* HAVE_LIBCRYPTO */
2718  delete_isupport("INVEX");
2719  delete_isupport("EXCEPTS");
2720 }
2721
2722 /* flush_deleted_I_P()
2723 *
2724 * inputs       - none
2725 * output       - none
2726 * side effects - This function removes I/P conf items
2727 */
2728 static void
2729 flush_deleted_I_P(void)
2730 {
2731  dlink_node *ptr;
2732  dlink_node *next_ptr;
2733  struct ConfItem *conf;
2734  struct AccessItem *aconf;
2735  dlink_list * free_items [] = {
2736    &server_items, &oconf_items, NULL
2737  };
2738  dlink_list ** iterator = free_items; /* C is dumb */
2739
2740  /* flush out deleted I and P lines
2741   * although still in use.
2742   */
2743  for (; *iterator != NULL; iterator++)
2744  {
2745    DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2746    {
2747      conf = ptr->data;
2748      aconf = (struct AccessItem *)map_to_conf(conf);
2749
2750      if (IsConfIllegal(aconf))
2751      {
2752        dlinkDelete(ptr, *iterator);
2753
2754        if (aconf->clients == 0)
2755          delete_conf_item(conf);
2756      }
2757    }
2758  }
2759 }
2760
2761 /* get_conf_name()
2762 *
2763 * inputs       - type of conf file to return name of file for
2764 * output       - pointer to filename for type of conf
2765 * side effects - none
2766 */
2767 const char *
2768 get_conf_name(ConfType type)
2769 {
2770  switch (type)
2771  {
2772    case CONF_TYPE:
2773      return ConfigFileEntry.configfile;
2774      break;
2775    case KLINE_TYPE:
2776      return ConfigFileEntry.klinefile;
2777      break;
2778    case RKLINE_TYPE:
2779      return ConfigFileEntry.rklinefile;
2780      break;
2781    case DLINE_TYPE:
2782      return ConfigFileEntry.dlinefile;
2783      break;
2784    case XLINE_TYPE:
2785      return ConfigFileEntry.xlinefile;
2786      break;
2787    case RXLINE_TYPE:
2788      return ConfigFileEntry.rxlinefile;
2789      break;
2790    case CRESV_TYPE:
2791      return ConfigFileEntry.cresvfile;
2792      break;
2793    case NRESV_TYPE:
2794      return ConfigFileEntry.nresvfile;
2795      break;
2796    case GLINE_TYPE:
2797      return ConfigFileEntry.glinefile;
2798      break;
2799
2800    default:
2801      return NULL;  /* This should NEVER HAPPEN since we call this function
2802                       only with the above values, this will cause us to core
2803                       at some point if this happens so we know where it was */
2804  }
2805 }
2806
2807 #define BAD_PING (-1)
2808
2809 /* get_conf_ping()
2810 *
2811 * inputs       - pointer to struct AccessItem
2812 *              - pointer to a variable that receives ping warning time
2813 * output       - ping frequency
2814 * side effects - NONE
2815 */
2816 static int
2817 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2818 {
2819  struct ClassItem *aclass;
2820  struct AccessItem *aconf;
2821
2822  if (conf != NULL)
2823  {
2824    aconf = (struct AccessItem *)map_to_conf(conf);
2825    if (aconf->class_ptr != NULL)
2826    {
2827      aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2828      *pingwarn = PingWarning(aclass);
2829      return PingFreq(aclass);
2830    }
2831  }
2832
2833  return BAD_PING;
2834 }
2835
2836 /* get_client_class()
2837 *
2838 * inputs       - pointer to client struct
2839 * output       - pointer to name of class
2840 * side effects - NONE
2841 */
2842 const char *
2843 get_client_class(struct Client *target_p)
2844 {
2845  dlink_node *ptr;
2846  struct ConfItem *conf;
2847  struct AccessItem *aconf;
2848
2849  if (target_p != NULL && !IsMe(target_p) &&
2850      target_p->localClient->confs.head != NULL)
2851  {
2852    DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2853    {
2854      conf = ptr->data;
2855
2856      if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2857          conf->type == OPER_TYPE)
2858      {
2859        aconf = (struct AccessItem *) map_to_conf(conf);
2860        if (aconf->class_ptr != NULL)
2861          return aconf->class_ptr->name;
2862      }
2863    }
2864  }
2865
2866  return "default";
2867 }
2868
2869 /* get_client_ping()
2870 *
2871 * inputs       - pointer to client struct
2872 *              - pointer to a variable that receives ping warning time
2873 * output       - ping frequency
2874 * side effects - NONE
2875 */
2876 int
2877 get_client_ping(struct Client *target_p, int *pingwarn)
2878 {
2879  int ping;
2880  struct ConfItem *conf;
2881  dlink_node *nlink;
2882
2883  if (target_p->localClient->confs.head != NULL)
2884    DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2885    {
2886      conf = nlink->data;
2887
2888      if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2889          (conf->type == OPER_TYPE))
2890      {
2891        ping = get_conf_ping(conf, pingwarn);
2892        if (ping > 0)
2893          return ping;
2894      }
2895    }
2896
2897  *pingwarn = 0;
2898  return DEFAULT_PINGFREQUENCY;
2899 }
2900
2901 /* find_class()
2902 *
2903 * inputs       - string name of class
2904 * output       - corresponding Class pointer
2905 * side effects - NONE
2906 */
2907 struct ConfItem *
2908 find_class(const char *classname)
2909 {
2910  struct ConfItem *conf;
2911
2912  if ((conf = find_exact_name_conf(CLASS_TYPE, classname, NULL, NULL)) != NULL)
2913    return conf;
2914
2915  return class_default;
2916 }
2917
2918 /* check_class()
2919 *
2920 * inputs       - NONE
2921 * output       - NONE
2922 * side effects -
2923 */
2924 void
2925 check_class(void)
2926 {
2927  dlink_node *ptr = NULL, *next_ptr = NULL;
2928
2929  DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2930  {
2931    struct ClassItem *aclass = map_to_conf(ptr->data);
2932
2933    if (!aclass->active && !CurrUserCount(aclass))
2934    {
2935      destroy_cidr_class(aclass);
2936      delete_conf_item(ptr->data);
2937    }
2938  }
2939 }
2940
2941 /* init_class()
2942 *
2943 * inputs       - NONE
2944 * output       - NONE
2945 * side effects -
2946 */
2947 void
2948 init_class(void)
2949 {
2950  struct ClassItem *aclass;
2951
2952  class_default = make_conf_item(CLASS_TYPE);
2953
2954  aclass = map_to_conf(class_default);
2955  aclass->active = 1;
2956  DupString(class_default->name, "default");
2957  ConFreq(aclass)  = DEFAULT_CONNECTFREQUENCY;
2958  PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
2959  MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
2960  MaxSendq(aclass) = DEFAULT_SENDQ;
2961
2962  client_check_cb = register_callback("check_client", check_client);
2963 }
2964
2965 /* get_sendq()
2966 *
2967 * inputs       - pointer to client
2968 * output       - sendq for this client as found from its class
2969 * side effects - NONE
2970 */
2971 unsigned int
2972 get_sendq(struct Client *client_p)
2973 {
2974  unsigned int sendq = DEFAULT_SENDQ;
2975  dlink_node *ptr;
2976  struct ConfItem *conf;
2977  struct ConfItem *class_conf;
2978  struct ClassItem *aclass;
2979  struct AccessItem *aconf;
2980
2981  if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2982  {
2983    DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2984    {
2985      conf = ptr->data;
2986      if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2987          || (conf->type == CLIENT_TYPE))
2988      {
2989        aconf = (struct AccessItem *)map_to_conf(conf);
2990        if ((class_conf = aconf->class_ptr) == NULL)
2991          continue;
2992        aclass = (struct ClassItem *)map_to_conf(class_conf);
2993        sendq = MaxSendq(aclass);
2994        return sendq;
2995      }
2996    }
2997  }
2998  /* XXX return a default?
2999   * if here, then there wasn't an attached conf with a sendq
3000   * that is very bad -Dianora
3001   */
3002  return DEFAULT_SENDQ;
1588   }
1589  
1590   /* conf_add_class_to_conf()
1591   *
1592   * inputs       - pointer to config item
1593   * output       - NONE
1594 < * side effects - Add a class pointer to a conf
1594 > * side effects - Add a class pointer to a conf
1595   */
1596   void
1597 < conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
1597 > conf_add_class_to_conf(struct MaskItem *conf, const char *class_name)
1598   {
1599 <  struct AccessItem *aconf = map_to_conf(conf);
3015 <  struct ClassItem *class = NULL;
3016 <
3017 <  if (class_name == NULL)
1599 >  if (class_name == NULL)
1600    {
1601 <    aconf->class_ptr = class_default;
1601 >    conf->class = class_default;
1602  
1603 <    if (conf->type == CLIENT_TYPE)
1604 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1605 <                           "Warning *** Defaulting to default class for %s@%s",
1606 <                           aconf->user, aconf->host);
1603 >    if (conf->type == CONF_CLIENT)
1604 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1605 >                           "Warning *** Defaulting to default class for %s@%s",
1606 >                           conf->user, conf->host);
1607      else
1608 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1609 <                           "Warning *** Defaulting to default class for %s",
1610 <                           conf->name);
1608 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1609 >                           "Warning *** Defaulting to default class for %s",
1610 >                           conf->name);
1611    }
1612    else
1613 <    aconf->class_ptr = find_class(class_name);
1613 >    conf->class = class_find(class_name, 1);
1614  
1615 <  if (aconf->class_ptr)
3034 <    class = map_to_conf(aconf->class_ptr);
3035 <
3036 <  if (aconf->class_ptr == NULL || !class->active)
1615 >  if (conf->class == NULL)
1616    {
1617 <    if (conf->type == CLIENT_TYPE)
1618 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1619 <                           "Warning *** Defaulting to default class for %s@%s",
1620 <                           aconf->user, aconf->host);
1617 >    if (conf->type == CONF_CLIENT)
1618 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1619 >                           "Warning *** Defaulting to default class for %s@%s",
1620 >                           conf->user, conf->host);
1621      else
1622 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1623 <                           "Warning *** Defaulting to default class for %s",
1624 <                           conf->name);
1625 <    aconf->class_ptr = class_default;
3047 <  }
3048 < }
3049 <
3050 < /* conf_add_server()
3051 < *
3052 < * inputs       - pointer to config item
3053 < *              - pointer to link count already on this conf
3054 < * output       - NONE
3055 < * side effects - Add a connect block
3056 < */
3057 < int
3058 < conf_add_server(struct ConfItem *conf, const char *class_name)
3059 < {
3060 <  struct AccessItem *aconf;
3061 <  struct split_nuh_item nuh;
3062 <  char conf_user[USERLEN + 1];
3063 <  char conf_host[HOSTLEN + 1];
3064 <
3065 <  aconf = map_to_conf(conf);
3066 <
3067 <  conf_add_class_to_conf(conf, class_name);
3068 <
3069 <  if (!aconf->host || !conf->name)
3070 <  {
3071 <    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
3072 <    ilog(LOG_TYPE_IRCD, "Bad connect block");
3073 <    return -1;
3074 <  }
3075 <
3076 <  if (EmptyString(aconf->passwd) && !IsConfCryptLink(aconf))
3077 <  {
3078 <    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
3079 <                         conf->name);
3080 <    ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
3081 <    return -1;
1622 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1623 >                           "Warning *** Defaulting to default class for %s",
1624 >                           conf->name);
1625 >    conf->class = class_default;
1626    }
3083
3084  nuh.nuhmask  = aconf->host;
3085  nuh.nickptr  = NULL;
3086  nuh.userptr  = conf_user;
3087  nuh.hostptr  = conf_host;
3088
3089  nuh.nicksize = 0;
3090  nuh.usersize = sizeof(conf_user);
3091  nuh.hostsize = sizeof(conf_host);
3092
3093  split_nuh(&nuh);
3094
3095  MyFree(aconf->host);
3096  aconf->host = NULL;
3097
3098  DupString(aconf->user, conf_user); /* somehow username checking for servers
3099                                 got lost in H6/7, will have to be re-added */
3100  DupString(aconf->host, conf_host);
3101
3102  lookup_confhost(conf);
3103
3104  return 0;
1627   }
1628  
1629   /* yyerror()
# Line 3119 | Line 1641 | yyerror(const char *msg)
1641      return;
1642  
1643    strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1644 <  sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
1644 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1645 >                       "\"%s\", line %u: %s: %s",
1646                         conffilebuf, lineno + 1, msg, newlinebuf);
1647    ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1648         conffilebuf, lineno + 1, msg, newlinebuf);
1649   }
1650  
1651 < int
1652 < conf_fbgets(char *lbuf, unsigned int max_size, FBFILE *fb)
1651 > void
1652 > conf_error_report(const char *msg)
1653   {
1654 <  if (fbgets(lbuf, max_size, fb) == NULL)
3132 <    return 0;
3133 <
3134 <  return strlen(lbuf);
3135 < }
1654 >  char newlinebuf[IRCD_BUFSIZE];
1655  
1656 < int
1657 < conf_yy_fatal_error(const char *msg)
1658 < {
1659 <  return 0;
1656 >  strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1657 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1658 >                       "\"%s\", line %u: %s: %s",
1659 >                       conffilebuf, lineno + 1, msg, newlinebuf);
1660 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1661 >       conffilebuf, lineno + 1, msg, newlinebuf);
1662   }
1663  
1664   /*
1665   * valid_tkline()
1666 < *
1666 > *
1667   * inputs       - pointer to ascii string to check
1668   *              - whether the specified time is in seconds or minutes
1669   * output       - -1 not enough parameters
# Line 3151 | Line 1672 | conf_yy_fatal_error(const char *msg)
1672   * Originally written by Dianora (Diane, db@db.net)
1673   */
1674   time_t
1675 < valid_tkline(const char *p, int minutes)
1675 > valid_tkline(const char *data, const int minutes)
1676   {
1677 +  const unsigned char *p = (const unsigned char *)data;
1678 +  unsigned char tmpch = '\0';
1679    time_t result = 0;
1680  
1681 <  for (; *p; ++p)
1681 >  while ((tmpch = *p++))
1682    {
1683 <    if (!IsDigit(*p))
1683 >    if (!IsDigit(tmpch))
1684        return 0;
1685  
1686      result *= 10;
1687 <    result += ((*p) & 0xF);
1687 >    result += (tmpch & 0xF);
1688    }
1689  
1690    /*
1691 <   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1691 >   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1692     * i.e. they specifically use 0, I am going to return 1 instead
1693     * as a return value of non-zero is used to flag it as a temporary kline
1694     */
1695    if (result == 0)
1696      result = 1;
1697  
1698 <  /*
1698 >  /*
1699     * If the incoming time is in seconds convert it to minutes for the purpose
1700     * of this calculation
1701     */
1702    if (!minutes)
1703 <    result = result / (time_t)60;
1703 >    result = result / 60;
1704  
1705    if (result > MAX_TDKLINE_TIME)
1706      result = MAX_TDKLINE_TIME;
1707  
1708 <  result = result * (time_t)60;  /* turn it into seconds */
1708 >  result = result * 60;  /* turn it into seconds */
1709  
1710    return result;
1711   }
1712  
1713 + /* valid_wild_card_simple()
1714 + *
1715 + * inputs       - data to check for sufficient non-wildcard characters
1716 + * outputs      - 1 if valid, else 0
1717 + * side effects - none
1718 + */
1719 + int
1720 + valid_wild_card_simple(const char *data)
1721 + {
1722 +  const unsigned char *p = (const unsigned char *)data;
1723 +  unsigned char tmpch = '\0';
1724 +  unsigned int nonwild = 0;
1725 +
1726 +  while ((tmpch = *p++))
1727 +  {
1728 +    if (tmpch == '\\' && *p)
1729 +    {
1730 +      ++p;
1731 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1732 +        return 1;
1733 +    }
1734 +    else if (!IsMWildChar(tmpch))
1735 +    {
1736 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1737 +        return 1;
1738 +    }
1739 +  }
1740 +
1741 +  return 0;
1742 + }
1743 +
1744   /* valid_wild_card()
1745   *
1746   * input        - pointer to client
# Line 3198 | Line 1752 | valid_tkline(const char *p, int minutes)
1752   int
1753   valid_wild_card(struct Client *source_p, int warn, int count, ...)
1754   {
1755 <  char *p;
1756 <  char tmpch;
3203 <  int nonwild = 0;
1755 >  unsigned char tmpch = '\0';
1756 >  unsigned int nonwild = 0;
1757    va_list args;
1758  
1759    /*
# Line 3219 | Line 1772 | valid_wild_card(struct Client *source_p,
1772  
1773    while (count--)
1774    {
1775 <    p = va_arg(args, char *);
1775 >    const unsigned char *p = va_arg(args, const unsigned char *);
1776      if (p == NULL)
1777        continue;
1778  
# Line 3232 | Line 1785 | valid_wild_card(struct Client *source_p,
1785           * break - no point in searching further.
1786           */
1787          if (++nonwild >= ConfigFileEntry.min_nonwildcard)
1788 +        {
1789 +          va_end(args);
1790            return 1;
1791 +        }
1792        }
1793      }
1794    }
1795  
1796    if (warn)
1797 <    sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
1798 <               me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
1797 >    sendto_one_notice(source_p, &me,
1798 >                      ":Please include at least %u non-wildcard characters with the mask",
1799 >                      ConfigFileEntry.min_nonwildcard);
1800 >  va_end(args);
1801    return 0;
1802   }
1803  
# Line 3253 | Line 1811 | valid_wild_card(struct Client *source_p,
1811   *              - parse_flags bit map of things to test
1812   *              - pointer to user or string to parse into
1813   *              - pointer to host or NULL to parse into if non NULL
1814 < *              - pointer to optional tkline time or NULL
1814 > *              - pointer to optional tkline time or NULL
1815   *              - pointer to target_server to parse into if non NULL
1816   *              - pointer to reason to parse into
1817   *
# Line 3275 | Line 1833 | valid_wild_card(struct Client *source_p,
1833   */
1834   int
1835   parse_aline(const char *cmd, struct Client *source_p,
1836 <            int parc, char **parv,
1837 <            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1838 <            char **target_server, char **reason)
1836 >            int parc, char **parv,
1837 >            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1838 >            char **target_server, char **reason)
1839   {
1840    int found_tkline_time=0;
1841 <  static char def_reason[] = "No Reason";
1841 >  static char def_reason[] = CONF_NOREASON;
1842    static char user[USERLEN*4+1];
1843    static char host[HOSTLEN*4+1];
1844  
# Line 3298 | Line 1856 | parse_aline(const char *cmd, struct Clie
1856        *tkline_time = found_tkline_time;
1857      else
1858      {
1859 <      sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3302 <                 me.name, source_p->name, cmd);
1859 >      sendto_one_notice(source_p, &me, ":temp_line not supported by %s", cmd);
1860        return -1;
1861      }
1862    }
1863  
1864    if (parc == 0)
1865    {
1866 <    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3310 <               me.name, source_p->name, cmd);
1866 >    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1867      return -1;
1868    }
1869  
# Line 3321 | Line 1877 | parse_aline(const char *cmd, struct Clie
1877      *up_p = user;
1878      *h_p = host;
1879    }
1880 <
1880 >
1881    parc--;
1882    parv++;
1883  
# Line 3334 | Line 1890 | parse_aline(const char *cmd, struct Clie
1890  
1891        if (target_server == NULL)
1892        {
1893 <        sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
1894 <                   me.name, source_p->name, cmd);
3339 <        return -1;
1893 >        sendto_one_notice(source_p, &me, ":ON server not supported by %s", cmd);
1894 >        return -1;
1895        }
1896  
1897        if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
1898        {
1899 <        sendto_one(source_p, form_str(ERR_NOPRIVS),
3345 <                   me.name, source_p->name, "remoteban");
1899 >        sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "remoteban");
1900          return -1;
1901        }
1902  
1903        if (parc == 0 || EmptyString(*parv))
1904        {
1905 <        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1906 <                   me.name, source_p->name, cmd);
3353 <        return -1;
1905 >        sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1906 >        return -1;
1907        }
1908  
1909        *target_server = *parv;
# Line 3363 | Line 1916 | parse_aline(const char *cmd, struct Clie
1916         * caller probably NULL'd it first, but no harm to do it again -db
1917         */
1918        if (target_server != NULL)
1919 <        *target_server = NULL;
1919 >        *target_server = NULL;
1920      }
1921    }
1922  
# Line 3371 | Line 1924 | parse_aline(const char *cmd, struct Clie
1924    {
1925      if (strchr(user, '!') != NULL)
1926      {
1927 <      sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3375 <                 me.name, source_p->name);
1927 >      sendto_one_notice(source_p, &me, ":Invalid character '!' in kline");
1928        return -1;
1929      }
1930  
# Line 3389 | Line 1941 | parse_aline(const char *cmd, struct Clie
1941      {
1942        *reason = *parv;
1943        if (!valid_comment(source_p, *reason, 1))
1944 <        return -1;
1944 >        return -1;
1945      }
1946      else
1947        *reason = def_reason;
# Line 3428 | Line 1980 | find_user_host(struct Client *source_p,
1980      {
1981        *(hostp++) = '\0';                       /* short and squat */
1982        if (*user_host_or_nick)
1983 <        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
1983 >        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
1984        else
1985 <        strcpy(luser, "*");
1985 >        strcpy(luser, "*");
1986 >
1987        if (*hostp)
1988 <        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
1988 >        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
1989        else
1990 <        strcpy(lhost, "*");
1990 >        strcpy(lhost, "*");
1991      }
1992      else
1993      {
1994        luser[0] = '*';             /* no @ found, assume its *@somehost */
1995 <      luser[1] = '\0';    
1995 >      luser[1] = '\0';
1996        strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
1997      }
1998 <    
1998 >
1999      return 1;
2000    }
2001 <  else if (!(flags & NOUSERLOOKUP))
2001 >  else
2002    {
2003      /* Try to find user@host mask from nick */
2004      /* Okay to use source_p as the first param, because source_p == client_p */
2005 <    if ((target_p =
2006 <        find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
2007 <      return 0;
2005 >    if ((target_p =
2006 >        find_chasing(source_p, user_host_or_nick)) == NULL)
2007 >      return 0;  /* find_chasing sends ERR_NOSUCHNICK */
2008  
2009      if (IsExemptKline(target_p))
2010      {
2011        if (!IsServer(source_p))
2012 <        sendto_one(source_p,
3460 <                   ":%s NOTICE %s :%s is E-lined",
3461 <                   me.name, source_p->name, target_p->name);
2012 >        sendto_one_notice(source_p, &me, ":%s is E-lined", target_p->name);
2013        return 0;
2014      }
2015  
# Line 3493 | Line 2044 | find_user_host(struct Client *source_p,
2044   int
2045   valid_comment(struct Client *source_p, char *comment, int warn)
2046   {
3496  if (strchr(comment, '"'))
3497  {
3498    if (warn)
3499      sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3500                 me.name, source_p->name);
3501    return 0;
3502  }
3503
2047    if (strlen(comment) > REASONLEN)
2048      comment[REASONLEN-1] = '\0';
2049  
# Line 3515 | Line 2058 | valid_comment(struct Client *source_p, c
2058   * side effects - none
2059   */
2060   int
2061 < match_conf_password(const char *password, const struct AccessItem *aconf)
2061 > match_conf_password(const char *password, const struct MaskItem *conf)
2062   {
2063    const char *encr = NULL;
2064  
2065 <  if (password == NULL || aconf->passwd == NULL)
2065 >  if (EmptyString(password) || EmptyString(conf->passwd))
2066      return 0;
2067  
2068 <  if (aconf->flags & CONF_FLAGS_ENCRYPTED)
2069 <  {
3527 <    /* use first two chars of the password they send in as salt */
3528 <    /* If the password in the conf is MD5, and ircd is linked
3529 <     * to scrypt on FreeBSD, or the standard crypt library on
3530 <     * glibc Linux, then this code will work fine on generating
3531 <     * the proper encrypted hash for comparison.
3532 <     */
3533 <    if (*aconf->passwd)
3534 <      encr = crypt(password, aconf->passwd);
3535 <    else
3536 <      encr = "";
3537 <  }
2068 >  if (conf->flags & CONF_FLAGS_ENCRYPTED)
2069 >    encr = crypt(password, conf->passwd);
2070    else
2071      encr = password;
2072  
2073 <  return !strcmp(encr, aconf->passwd);
2073 >  return encr && !strcmp(encr, conf->passwd);
2074   }
2075  
2076   /*
# Line 3546 | Line 2078 | match_conf_password(const char *password
2078   *
2079   * inputs       - client sending the cluster
2080   *              - command name "KLINE" "XLINE" etc.
2081 < *              - capab -- CAP_KLN etc. from s_serv.h
2082 < *              - cluster type -- CLUSTER_KLINE etc. from s_conf.h
2081 > *              - capab -- CAP_KLN etc. from server.h
2082 > *              - cluster type -- CLUSTER_KLINE etc. from conf.h
2083   *              - pattern and args to send along
2084   * output       - none
2085   * side effects - Take source_p send the pattern with args given
# Line 3558 | Line 2090 | cluster_a_line(struct Client *source_p,
2090                 int capab, int cluster_type, const char *pattern, ...)
2091   {
2092    va_list args;
2093 <  char buffer[IRCD_BUFSIZE];
2093 >  char buffer[IRCD_BUFSIZE] = "";
2094    const dlink_node *ptr = NULL;
2095  
2096    va_start(args, pattern);
# Line 3567 | Line 2099 | cluster_a_line(struct Client *source_p,
2099  
2100    DLINK_FOREACH(ptr, cluster_items.head)
2101    {
2102 <    const struct ConfItem *conf = ptr->data;
2102 >    const struct MaskItem *conf = ptr->data;
2103  
2104      if (conf->flags & cluster_type)
2105        sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
2106 <                         "%s %s %s", command, conf->name, buffer);
2106 >                         "%s %s %s", command, conf->name, buffer);
2107    }
2108   }
2109  
# Line 3619 | Line 2151 | split_nuh(struct split_nuh_item *const i
2151    {
2152      *p = '\0';
2153  
2154 <    if (iptr->nickptr && *iptr->nuhmask != '\0')
2154 >    if (iptr->nickptr && *iptr->nuhmask)
2155        strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
2156  
2157 <    if ((q = strchr(++p, '@'))) {
2157 >    if ((q = strchr(++p, '@')))
2158 >    {
2159        *q++ = '\0';
2160  
2161 <      if (*p != '\0')
2161 >      if (*p)
2162          strlcpy(iptr->userptr, p, iptr->usersize);
2163  
2164 <      if (*q != '\0')
2164 >      if (*q)
2165          strlcpy(iptr->hostptr, q, iptr->hostsize);
2166      }
2167      else
2168      {
2169 <      if (*p != '\0')
2169 >      if (*p)
2170          strlcpy(iptr->userptr, p, iptr->usersize);
2171      }
2172    }
# Line 3645 | Line 2178 | split_nuh(struct split_nuh_item *const i
2178        /* if found a @ */
2179        *p++ = '\0';
2180  
2181 <      if (*iptr->nuhmask != '\0')
2181 >      if (*iptr->nuhmask)
2182          strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
2183  
2184 <      if (*p != '\0')
2184 >      if (*p)
2185          strlcpy(iptr->hostptr, p, iptr->hostsize);
2186      }
2187      else
# Line 3661 | Line 2194 | split_nuh(struct split_nuh_item *const i
2194      }
2195    }
2196   }
3664
3665 /*
3666 * flags_to_ascii
3667 *
3668 * inputs       - flags is a bitmask
3669 *              - pointer to table of ascii letters corresponding
3670 *                to each bit
3671 *              - flag 1 for convert ToLower if bit missing
3672 *                0 if ignore.
3673 * output       - none
3674 * side effects - string pointed to by p has bitmap chars written to it
3675 */
3676 static void
3677 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3678               int lowerit)
3679 {
3680  unsigned int mask = 1;
3681  int i = 0;
3682
3683  for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3684  {
3685    if (flags & mask)
3686      *p++ = bit_table[i];
3687    else if (lowerit)
3688      *p++ = ToLower(bit_table[i]);
3689  }
3690  *p = '\0';
3691 }
3692
3693 /*
3694 * cidr_limit_reached
3695 *
3696 * inputs       - int flag allowing over_rule of limits
3697 *              - pointer to the ip to be added
3698 *              - pointer to the class
3699 * output       - non zero if limit reached
3700 *                0 if limit not reached
3701 * side effects -
3702 */
3703 static int
3704 cidr_limit_reached(int over_rule,
3705                   struct irc_ssaddr *ip, struct ClassItem *aclass)
3706 {
3707  dlink_node *ptr = NULL;
3708  struct CidrItem *cidr;
3709
3710  if (NumberPerCidr(aclass) <= 0)
3711    return 0;
3712
3713  if (ip->ss.ss_family == AF_INET)
3714  {
3715    if (CidrBitlenIPV4(aclass) <= 0)
3716      return 0;
3717
3718    DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3719    {
3720      cidr = ptr->data;
3721      if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3722      {
3723        if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3724          return -1;
3725        cidr->number_on_this_cidr++;
3726        return 0;
3727      }
3728    }
3729    cidr = MyMalloc(sizeof(struct CidrItem));
3730    cidr->number_on_this_cidr = 1;
3731    cidr->mask = *ip;
3732    mask_addr(&cidr->mask, CidrBitlenIPV4(aclass));
3733    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3734  }
3735 #ifdef IPV6
3736  else if (CidrBitlenIPV6(aclass) > 0)
3737  {
3738    DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3739    {
3740      cidr = ptr->data;
3741      if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3742      {
3743        if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3744          return -1;
3745        cidr->number_on_this_cidr++;
3746        return 0;
3747      }
3748    }
3749    cidr = MyMalloc(sizeof(struct CidrItem));
3750    cidr->number_on_this_cidr = 1;
3751    cidr->mask = *ip;
3752    mask_addr(&cidr->mask, CidrBitlenIPV6(aclass));
3753    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3754  }
3755 #endif
3756  return 0;
3757 }
3758
3759 /*
3760 * remove_from_cidr_check
3761 *
3762 * inputs       - pointer to the ip to be removed
3763 *              - pointer to the class
3764 * output       - NONE
3765 * side effects -
3766 */
3767 static void
3768 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3769 {
3770  dlink_node *ptr = NULL;
3771  dlink_node *next_ptr = NULL;
3772  struct CidrItem *cidr;
3773
3774  if (NumberPerCidr(aclass) == 0)
3775    return;
3776
3777  if (ip->ss.ss_family == AF_INET)
3778  {
3779    if (CidrBitlenIPV4(aclass) <= 0)
3780      return;
3781
3782    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3783    {
3784      cidr = ptr->data;
3785      if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3786      {
3787        cidr->number_on_this_cidr--;
3788        if (cidr->number_on_this_cidr == 0)
3789        {
3790          dlinkDelete(ptr, &aclass->list_ipv4);
3791          MyFree(cidr);
3792          return;
3793        }
3794      }
3795    }
3796  }
3797 #ifdef IPV6
3798  else if (CidrBitlenIPV6(aclass) > 0)
3799  {
3800    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3801    {
3802      cidr = ptr->data;
3803      if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3804      {
3805        cidr->number_on_this_cidr--;
3806        if (cidr->number_on_this_cidr == 0)
3807        {
3808          dlinkDelete(ptr, &aclass->list_ipv6);
3809          MyFree(cidr);
3810          return;
3811        }
3812      }
3813    }
3814  }
3815 #endif
3816 }
3817
3818 static void
3819 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3820                  dlink_list *old_list, dlink_list *new_list, int changed)
3821 {
3822  dlink_node *ptr;
3823  struct Client *client_p;
3824  struct ConfItem *conf;
3825  struct AccessItem *aconf;
3826
3827  if (!changed)
3828  {
3829    *new_list = *old_list;
3830    old_list->head = old_list->tail = NULL;
3831    old_list->length = 0;
3832    return;
3833  }
3834
3835  DLINK_FOREACH(ptr, local_client_list.head)
3836  {
3837    client_p = ptr->data;
3838    if (client_p->localClient->aftype != aftype)
3839      continue;
3840    if (dlink_list_length(&client_p->localClient->confs) == 0)
3841      continue;
3842
3843    conf = client_p->localClient->confs.tail->data;
3844    if (conf->type == CLIENT_TYPE)
3845    {
3846      aconf = map_to_conf(conf);
3847      if (aconf->class_ptr == oldcl)
3848        cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3849    }
3850  }
3851 }
3852
3853 /*
3854 * rebuild_cidr_class
3855 *
3856 * inputs       - pointer to old conf
3857 *              - pointer to new_class
3858 * output       - none
3859 * side effects - rebuilds the class link list of cidr blocks
3860 */
3861 void
3862 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3863 {
3864  struct ClassItem *old_class = map_to_conf(conf);
3865
3866  if (NumberPerCidr(old_class) > 0 && NumberPerCidr(new_class) > 0)
3867  {
3868    if (CidrBitlenIPV4(old_class) > 0 && CidrBitlenIPV4(new_class) > 0)
3869      rebuild_cidr_list(AF_INET, conf, new_class,
3870                        &old_class->list_ipv4, &new_class->list_ipv4,
3871                        CidrBitlenIPV4(old_class) != CidrBitlenIPV4(new_class));
3872
3873 #ifdef IPV6
3874    if (CidrBitlenIPV6(old_class) > 0 && CidrBitlenIPV6(new_class) > 0)
3875      rebuild_cidr_list(AF_INET6, conf, new_class,
3876                        &old_class->list_ipv6, &new_class->list_ipv6,
3877                        CidrBitlenIPV6(old_class) != CidrBitlenIPV6(new_class));
3878 #endif
3879  }
3880
3881  destroy_cidr_class(old_class);
3882 }
3883
3884 /*
3885 * destroy_cidr_list
3886 *
3887 * inputs       - pointer to class dlink list of cidr blocks
3888 * output       - none
3889 * side effects - completely destroys the class link list of cidr blocks
3890 */
3891 static void
3892 destroy_cidr_list(dlink_list *list)
3893 {
3894  dlink_node *ptr = NULL, *next_ptr = NULL;
3895
3896  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3897  {
3898    dlinkDelete(ptr, list);
3899    MyFree(ptr->data);
3900  }
3901 }
3902
3903 /*
3904 * destroy_cidr_class
3905 *
3906 * inputs       - pointer to class
3907 * output       - none
3908 * side effects - completely destroys the class link list of cidr blocks
3909 */
3910 static void
3911 destroy_cidr_class(struct ClassItem *aclass)
3912 {
3913  destroy_cidr_list(&aclass->list_ipv4);
3914  destroy_cidr_list(&aclass->list_ipv6);
3915 }

Diff Legend

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