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 1243 by michael, Fri Sep 30 10:47:53 2011 UTC vs.
ircd-hybrid/trunk/src/conf.c (file contents), Revision 3215 by michael, Tue Mar 25 19:23:15 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"
29 < #include "s_conf.h"
30 > #include "conf.h"
31   #include "s_serv.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"
37   #include "irc_string.h"
38 #include "sprintf_irc.h"
38   #include "s_bsd.h"
39   #include "ircd.h"
40   #include "listener.h"
# Line 43 | Line 42
42   #include "modules.h"
43   #include "numeric.h"
44   #include "fdlist.h"
45 < #include "s_log.h"
45 > #include "log.h"
46   #include "send.h"
47   #include "s_gline.h"
49 #include "fileio.h"
48   #include "memory.h"
49 + #include "mempool.h"
50   #include "irc_res.h"
51   #include "userhost.h"
52   #include "s_user.h"
53   #include "channel_mode.h"
54   #include "parse.h"
55   #include "s_misc.h"
56 + #include "conf_db.h"
57 + #include "conf_class.h"
58 + #include "motd.h"
59 +
60  
61 < struct Callback *client_check_cb = NULL;
61 > struct config_channel_entry ConfigChannel;
62   struct config_server_hide ConfigServerHide;
63 + struct config_file_entry ConfigFileEntry;
64 + struct logging_entry ConfigLoggingEntry = { .use_logging = 1 };
65 + struct server_info ServerInfo;
66 + struct admin_info AdminInfo;
67  
68   /* general conf items link list root, other than k lines etc. */
69   dlink_list service_items = { NULL, NULL, 0 };
70   dlink_list server_items  = { NULL, NULL, 0 };
71   dlink_list cluster_items = { NULL, NULL, 0 };
65 dlink_list hub_items     = { NULL, NULL, 0 };
66 dlink_list leaf_items    = { NULL, NULL, 0 };
72   dlink_list oconf_items   = { NULL, NULL, 0 };
73   dlink_list uconf_items   = { NULL, NULL, 0 };
74   dlink_list xconf_items   = { NULL, NULL, 0 };
70 dlink_list rxconf_items  = { NULL, NULL, 0 };
71 dlink_list rkconf_items  = { NULL, NULL, 0 };
75   dlink_list nresv_items   = { NULL, NULL, 0 };
76 < 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 };
76 > dlink_list cresv_items = { NULL, NULL, 0 };
77  
78   extern unsigned int lineno;
79   extern char linebuf[];
80   extern char conffilebuf[IRCD_BUFSIZE];
87 extern char yytext[];
81   extern int yyparse(); /* defined in y.tab.c */
82  
83   struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
84  
85   /* internally defined functions */
86 < 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 *);
86 > static void read_conf(FILE *);
87   static void clear_out_old_conf(void);
98 static void flush_deleted_I_P(void);
88   static void expire_tklines(dlink_list *);
89   static void garbage_collect_ip_entries(void);
90   static int hash_ip(struct irc_ssaddr *);
91 < static int verify_access(struct Client *, const char *);
92 < static int attach_iline(struct Client *, struct ConfItem *);
91 > static int verify_access(struct Client *);
92 > static int attach_iline(struct Client *, struct MaskItem *);
93   static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
94 < static void parse_conf_file(int, int);
106 < static dlink_list *map_to_list(ConfType);
107 < static struct AccessItem *find_regexp_kline(const char *[]);
94 > static dlink_list *map_to_list(enum maskitem_type);
95   static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
96  
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;
97  
98   /* usually, with hash tables, you use a prime number...
99   * but in this case I am dealing with ip addresses,
# Line 128 | Line 104 | static struct ConfItem *class_default;
104   struct ip_entry
105   {
106    struct irc_ssaddr ip;
107 <  int count;
107 >  unsigned int count;
108    time_t last_attempt;
109    struct ip_entry *next;
110   };
111  
112   static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
113 < static BlockHeap *ip_entry_heap = NULL;
113 > static mp_pool_t *ip_entry_pool = NULL;
114   static int ip_entries_count = 0;
115  
116  
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
117   /* conf_dns_callback()
118   *
119 < * inputs       - pointer to struct AccessItem
119 > * inputs       - pointer to struct MaskItem
120   *              - pointer to DNSReply reply
121   * output       - none
122   * side effects - called when resolver query finishes
# Line 170 | Line 127 | unmap_conf_item(void *aconf)
127   static void
128   conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
129   {
130 <  struct AccessItem *aconf = vptr;
130 >  struct MaskItem *conf = vptr;
131  
132 <  aconf->dns_pending = 0;
132 >  conf->dns_pending = 0;
133  
134    if (addr != NULL)
135 <    memcpy(&aconf->ipnum, addr, sizeof(aconf->ipnum));
135 >    memcpy(&conf->addr, addr, sizeof(conf->addr));
136    else
137 <    aconf->dns_failed = 1;
137 >    conf->dns_failed = 1;
138   }
139  
140   /* conf_dns_lookup()
# Line 187 | Line 144 | conf_dns_callback(void *vptr, const stru
144   * allocate a dns_query and start ns lookup.
145   */
146   static void
147 < conf_dns_lookup(struct AccessItem *aconf)
147 > conf_dns_lookup(struct MaskItem *conf)
148   {
149 <  if (!aconf->dns_pending)
149 >  if (!conf->dns_pending)
150    {
151 <    aconf->dns_pending = 1;
152 <    gethost_byname(conf_dns_callback, aconf, aconf->host);
151 >    conf->dns_pending = 1;
152 >    gethost_byname(conf_dns_callback, conf, conf->host);
153    }
154   }
155  
156 < /* make_conf_item()
157 < *
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)
156 > struct MaskItem *
157 > conf_make(enum maskitem_type type)
158   {
159 <  struct ConfItem *conf = NULL;
160 <  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;
159 >  struct MaskItem *conf = MyMalloc(sizeof(*conf));
160 >  dlink_list *list = NULL;
161  
162 <  default:
163 <    conf = NULL;
164 <    break;
349 <  }
350 <
351 <  /* XXX Yes, this will core if default is hit. I want it to for now - db */
352 <  conf->type = type;
162 >  conf->type   = type;
163 >  conf->active = 1;
164 >  conf->aftype = AF_INET;
165  
166 +  if ((list = map_to_list(type)))
167 +    dlinkAdd(conf, &conf->node, list);
168    return conf;
169   }
170  
171   void
172 < delete_conf_item(struct ConfItem *conf)
172 > conf_free(struct MaskItem *conf)
173   {
174 <  dlink_node *m = NULL;
175 <  struct MatchItem *match_item;
176 <  struct AccessItem *aconf;
177 <  ConfType type = conf->type;
174 >  dlink_node *ptr = NULL, *ptr_next = NULL;
175 >  dlink_list *list = NULL;
176 >
177 >  if (conf->node.next)
178 >    if ((list = map_to_list(conf->type)))
179 >      dlinkDelete(&conf->node, list);
180  
181    MyFree(conf->name);
366  conf->name = NULL;
182  
183 <  switch(type)
184 <  {
185 <  case DLINE_TYPE:
186 <  case EXEMPTDLINE_TYPE:
187 <  case GLINE_TYPE:
188 <  case KLINE_TYPE:
189 <  case CLIENT_TYPE:
190 <  case OPER_TYPE:
191 <  case SERVER_TYPE:
192 <    aconf = map_to_conf(conf);
193 <
194 <    if (aconf->dns_pending)
195 <      delete_resolver_queries(aconf);
196 <    if (aconf->passwd != NULL)
197 <      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);
183 >  if (conf->dns_pending)
184 >    delete_resolver_queries(conf);
185 >  if (conf->passwd != NULL)
186 >    memset(conf->passwd, 0, strlen(conf->passwd));
187 >  if (conf->spasswd != NULL)
188 >    memset(conf->spasswd, 0, strlen(conf->spasswd));
189 >
190 >  conf->class = NULL;
191 >
192 >  MyFree(conf->passwd);
193 >  MyFree(conf->spasswd);
194 >  MyFree(conf->reason);
195 >  MyFree(conf->certfp);
196 >  MyFree(conf->user);
197 >  MyFree(conf->host);
198   #ifdef HAVE_LIBCRYPTO
199 <    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;
199 >  MyFree(conf->cipher_list);
200  
201 <  case ULINE_TYPE:
202 <    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;
201 >  if (conf->rsa_public_key)
202 >    RSA_free(conf->rsa_public_key);
203   #endif
204 <  case NRESV_TYPE:
205 <    match_item = map_to_conf(conf);
206 <    MyFree(match_item->user);
207 <    MyFree(match_item->host);
208 <    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;
204 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->hub_list.head)
205 >  {
206 >    MyFree(ptr->data);
207 >    dlinkDelete(ptr, &conf->hub_list);
208 >    free_dlink_node(ptr);
209    }
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 }
210  
211 < 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)
211 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->leaf_list.head)
212    {
213 <  case GDENY_TYPE:
214 <    DLINK_FOREACH(ptr, gdeny_items.head)
215 <    {
216 <      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;
213 >    MyFree(ptr->data);
214 >    dlinkDelete(ptr, &conf->leaf_list);
215 >    free_dlink_node(ptr);
216 >  }
217  
218 <  case LEAF_TYPE:
219 <    DLINK_FOREACH(ptr, leaf_items.head)
220 <    {
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;
218 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->exempt_list.head)
219 >  {
220 >    struct exempt *exptr = ptr->data;
221  
222 <  case GLINE_TYPE:
223 <  case KLINE_TYPE:
224 <  case DLINE_TYPE:
225 <  case EXEMPTDLINE_TYPE:
226 <  case CRESV_TYPE:
806 <  case NRESV_TYPE:
807 <  case CLUSTER_TYPE:
808 <  default:
809 <    break;
222 >    dlinkDelete(ptr, &conf->exempt_list);
223 >    MyFree(exptr->name);
224 >    MyFree(exptr->user);
225 >    MyFree(exptr->host);
226 >    MyFree(exptr);
227    }
228 +
229 +  MyFree(conf);
230   }
231  
232   /* check_client()
# Line 823 | Line 242 | report_confitem_types(struct Client *sou
242   *                Look for conf lines which have the same
243   *                status as the flags passed.
244   */
245 < static void *
246 < check_client(va_list args)
245 > int
246 > check_client(struct Client *source_p)
247   {
829  struct Client *source_p = va_arg(args, struct Client *);
830  const char *username = va_arg(args, const char *);
248    int i;
249 <
250 <  /* I'm already in big trouble if source_p->localClient is NULL -db */
251 <  if ((i = verify_access(source_p, username)))
835 <    ilog(L_INFO, "Access denied: %s[%s]",
249 >
250 >  if ((i = verify_access(source_p)))
251 >    ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
252           source_p->name, source_p->sockhost);
253  
254    switch (i)
255    {
256      case TOO_MANY:
257 <      sendto_realops_flags(UMODE_FULL, L_ALL,
257 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
258                             "Too many on IP for %s (%s).",
259 <                           get_client_name(source_p, SHOW_IP),
260 <                           source_p->sockhost);
261 <      ilog(L_INFO,"Too many connections on IP from %s.",
262 <           get_client_name(source_p, SHOW_IP));
259 >                           get_client_name(source_p, SHOW_IP),
260 >                           source_p->sockhost);
261 >      ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
262 >           get_client_name(source_p, SHOW_IP));
263        ++ServerStats.is_ref;
264 <      exit_client(source_p, &me, "No more connections allowed on that IP");
264 >      exit_client(source_p, "No more connections allowed on that IP");
265        break;
266  
267      case I_LINE_FULL:
268 <      sendto_realops_flags(UMODE_FULL, L_ALL,
269 <                           "I-line is full for %s (%s).",
270 <                           get_client_name(source_p, SHOW_IP),
271 <                           source_p->sockhost);
272 <      ilog(L_INFO,"Too many connections from %s.",
273 <           get_client_name(source_p, SHOW_IP));
268 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
269 >                           "auth{} block is full for %s (%s).",
270 >                           get_client_name(source_p, SHOW_IP),
271 >                           source_p->sockhost);
272 >      ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
273 >           get_client_name(source_p, SHOW_IP));
274        ++ServerStats.is_ref;
275 <      exit_client(source_p, &me,
860 <                "No more connections allowed in your connection class");
275 >      exit_client(source_p, "No more connections allowed in your connection class");
276        break;
277  
278      case NOT_AUTHORIZED:
279        ++ServerStats.is_ref;
280        /* jdc - lists server name & port connections are on */
281        /*       a purely cosmetical change */
282 <      sendto_realops_flags(UMODE_UNAUTH, L_ALL,
283 <                           "Unauthorized client connection from %s [%s] on [%s/%u].",
284 <                           get_client_name(source_p, SHOW_IP),
285 <                           source_p->sockhost,
286 <                           source_p->localClient->listener->name,
287 <                           source_p->localClient->listener->port);
288 <      ilog(L_INFO,
289 <          "Unauthorized client connection from %s on [%s/%u].",
290 <          get_client_name(source_p, SHOW_IP),
291 <          source_p->localClient->listener->name,
292 <          source_p->localClient->listener->port);
293 <
294 <      /* 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");
282 >      sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
283 >                           "Unauthorized client connection from %s [%s] on [%s/%u].",
284 >                           get_client_name(source_p, SHOW_IP),
285 >                           source_p->sockhost,
286 >                           source_p->localClient->listener->name,
287 >                           source_p->localClient->listener->port);
288 >      ilog(LOG_TYPE_IRCD,
289 >           "Unauthorized client connection from %s on [%s/%u].",
290 >           get_client_name(source_p, SHOW_IP),
291 >           source_p->localClient->listener->name,
292 >           source_p->localClient->listener->port);
293 >
294 >      exit_client(source_p, "You are not authorized to use this server");
295        break;
296  
297     case BANNED_CLIENT:
298 <     /*
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");
298 >     exit_client(source_p, "Banned");
299       ++ServerStats.is_ref;
300       break;
301  
# Line 911 | Line 304 | check_client(va_list args)
304       break;
305    }
306  
307 <  return (i < 0 ? NULL : source_p);
307 >  return (i < 0 ? 0 : 1);
308   }
309  
310   /* verify_access()
311   *
312   * inputs       - pointer to client to verify
920 *              - pointer to proposed username
313   * output       - 0 if success -'ve if not
314   * side effect  - find the first (best) I line to attach.
315   */
316   static int
317 < verify_access(struct Client *client_p, const char *username)
317 > verify_access(struct Client *client_p)
318   {
319 <  struct AccessItem *aconf = NULL, *rkconf = NULL;
320 <  struct ConfItem *conf = NULL;
929 <  char non_ident[USERLEN + 1] = { '~', '\0' };
930 <  const char *uhi[3];
319 >  struct MaskItem *conf = NULL;
320 >  char non_ident[USERLEN + 1] = "~";
321  
322    if (IsGotId(client_p))
323    {
324 <    aconf = find_address_conf(client_p->host, client_p->username,
325 <                             &client_p->localClient->ip,
326 <                             client_p->localClient->aftype,
324 >    conf = find_address_conf(client_p->host, client_p->username,
325 >                             &client_p->localClient->ip,
326 >                             client_p->localClient->aftype,
327                               client_p->localClient->passwd);
328    }
329    else
330    {
331 <    strlcpy(non_ident+1, username, sizeof(non_ident)-1);
332 <    aconf = find_address_conf(client_p->host,non_ident,
333 <                             &client_p->localClient->ip,
334 <                             client_p->localClient->aftype,
335 <                             client_p->localClient->passwd);
331 >    strlcpy(non_ident + 1, client_p->username, sizeof(non_ident) - 1);
332 >    conf = find_address_conf(client_p->host,non_ident,
333 >                             &client_p->localClient->ip,
334 >                             client_p->localClient->aftype,
335 >                             client_p->localClient->passwd);
336    }
337  
338 <  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)
338 >  if (conf)
339    {
340 <    if (IsConfClient(aconf) && !rkconf)
340 >    if (IsConfClient(conf))
341      {
342 <      conf = unmap_conf_item(aconf);
959 <
960 <      if (IsConfRedir(aconf))
342 >      if (IsConfRedir(conf))
343        {
344 <        sendto_one(client_p, form_str(RPL_REDIR),
345 <                   me.name, client_p->name,
346 <                   conf->name ? conf->name : "",
347 <                   aconf->port);
966 <        return(NOT_AUTHORIZED);
344 >        sendto_one_numeric(client_p, &me, RPL_REDIR,
345 >                           conf->name ? conf->name : "",
346 >                           conf->port);
347 >        return NOT_AUTHORIZED;
348        }
349  
350 <      if (IsConfDoIdentd(aconf))
351 <        SetNeedId(client_p);
350 >      if (IsConfDoIdentd(conf))
351 >        SetNeedId(client_p);
352  
353        /* Thanks for spoof idea amm */
354 <      if (IsConfDoSpoofIp(aconf))
354 >      if (IsConfDoSpoofIp(conf))
355        {
356 <        conf = unmap_conf_item(aconf);
357 <
358 <        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
978 <          sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
356 >        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(conf))
357 >          sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
358 >                               "%s spoofing: %s as %s",
359                                 client_p->name, client_p->host, conf->name);
360          strlcpy(client_p->host, conf->name, sizeof(client_p->host));
361 <        SetIPSpoof(client_p);
361 >        AddFlag(client_p, FLAGS_IP_SPOOFING | FLAGS_AUTH_SPOOF);
362        }
363  
364 <      return(attach_iline(client_p, conf));
364 >      return attach_iline(client_p, conf);
365      }
366 <    else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
366 >    else if (IsConfKill(conf) || (ConfigFileEntry.glines && IsConfGline(conf)))
367      {
368 <      /* XXX */
369 <      aconf = rkconf ? rkconf : aconf;
370 <      if (IsConfGline(aconf))
371 <        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);
368 >      if (IsConfGline(conf))
369 >        sendto_one_notice(client_p, &me, ":*** G-lined");
370 >      sendto_one_notice(client_p, &me, ":*** Banned: %s", conf->reason);
371 >      return BANNED_CLIENT;
372      }
373    }
374  
375 <  return(NOT_AUTHORIZED);
375 >  return NOT_AUTHORIZED;
376   }
377  
378   /* attach_iline()
# Line 1008 | Line 383 | verify_access(struct Client *client_p, c
383   * side effects - do actual attach
384   */
385   static int
386 < attach_iline(struct Client *client_p, struct ConfItem *conf)
386 > attach_iline(struct Client *client_p, struct MaskItem *conf)
387   {
388 <  struct AccessItem *aconf;
1014 <  struct ClassItem *aclass;
388 >  struct ClassItem *class = NULL;
389    struct ip_entry *ip_found;
390    int a_limit_reached = 0;
391 <  int local = 0, global = 0, ident = 0;
391 >  unsigned int local = 0, global = 0, ident = 0;
392 >
393 >  assert(conf->class);
394  
395    ip_found = find_or_add_ip(&client_p->localClient->ip);
396    ip_found->count++;
397    SetIpHash(client_p);
398  
399 <  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);
399 >  class = conf->class;
400  
401    count_user_host(client_p->username, client_p->host,
402                    &global, &local, &ident);
# Line 1033 | Line 405 | attach_iline(struct Client *client_p, st
405     * setting a_limit_reached if any limit is reached.
406     * - Dianora
407     */
408 <  if (MaxTotal(aclass) != 0 && CurrUserCount(aclass) >= MaxTotal(aclass))
408 >  if (class->max_total != 0 && class->ref_count >= class->max_total)
409      a_limit_reached = 1;
410 <  else if (MaxPerIp(aclass) != 0 && ip_found->count > MaxPerIp(aclass))
410 >  else if (class->max_perip != 0 && ip_found->count > class->max_perip)
411      a_limit_reached = 1;
412 <  else if (MaxLocal(aclass) != 0 && local >= MaxLocal(aclass))
412 >  else if (class->max_local != 0 && local >= class->max_local)
413      a_limit_reached = 1;
414 <  else if (MaxGlobal(aclass) != 0 && global >= MaxGlobal(aclass))
414 >  else if (class->max_global != 0 && global >= class->max_global)
415      a_limit_reached = 1;
416 <  else if (MaxIdent(aclass) != 0 && ident >= MaxIdent(aclass) &&
416 >  else if (class->max_ident != 0 && ident >= class->max_ident &&
417             client_p->username[0] != '~')
418      a_limit_reached = 1;
419  
420    if (a_limit_reached)
421    {
422 <    if (!IsConfExemptLimits(aconf))
422 >    if (!IsConfExemptLimits(conf))
423        return TOO_MANY;   /* Already at maximum allowed */
424  
425 <    sendto_one(client_p,
426 <               ":%s NOTICE %s :*** Your connection class is full, "
1055 <               "but you have exceed_limit = yes;", me.name, client_p->name);
425 >    sendto_one_notice(client_p, &me, ":*** Your connection class is full, "
426 >                      "but you have exceed_limit = yes;");
427    }
428  
429    return attach_conf(client_p, conf);
# Line 1068 | Line 439 | attach_iline(struct Client *client_p, st
439   void
440   init_ip_hash_table(void)
441   {
442 <  ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
1072 <    2 * hard_fdlimit);
442 >  ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
443    memset(ip_hash_table, 0, sizeof(ip_hash_table));
444   }
445  
# Line 1118 | Line 488 | find_or_add_ip(struct irc_ssaddr *ip_in)
488    if (ip_entries_count >= 2 * hard_fdlimit)
489      garbage_collect_ip_entries();
490  
491 <  newptr = BlockHeapAlloc(ip_entry_heap);
491 >  newptr = mp_pool_get(ip_entry_pool);
492 >  memset(newptr, 0, sizeof(*newptr));
493    ip_entries_count++;
494    memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
495  
# Line 1169 | Line 540 | remove_one_ip(struct irc_ssaddr *ip_in)
540      if (ptr->count > 0)
541        ptr->count--;
542      if (ptr->count == 0 &&
543 <        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
543 >        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
544      {
545        if (last_ptr != NULL)
546 <        last_ptr->next = ptr->next;
546 >        last_ptr->next = ptr->next;
547        else
548 <        ip_hash_table[hash_index] = ptr->next;
548 >        ip_hash_table[hash_index] = ptr->next;
549  
550 <      BlockHeapFree(ip_entry_heap, ptr);
550 >      mp_pool_release(ptr);
551        ip_entries_count--;
552        return;
553      }
# Line 1211 | Line 582 | hash_ip(struct irc_ssaddr *addr)
582      uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
583  
584      hash  = ip[0] ^ ip[3];
585 <    hash ^= hash >> 16;  
586 <    hash ^= hash >> 8;  
585 >    hash ^= hash >> 16;
586 >    hash ^= hash >> 8;
587      hash  = hash & (IP_HASH_SIZE - 1);
588      return hash;
589    }
# Line 1223 | Line 594 | hash_ip(struct irc_ssaddr *addr)
594  
595   /* count_ip_hash()
596   *
597 < * inputs        - pointer to counter of number of ips hashed
597 > * inputs        - pointer to counter of number of ips hashed
598   *               - pointer to memory used for ip hash
599   * output        - returned via pointers input
600   * side effects  - NONE
# Line 1279 | Line 650 | garbage_collect_ip_entries(void)
650            last_ptr->next = ptr->next;
651          else
652            ip_hash_table[i] = ptr->next;
653 <        BlockHeapFree(ip_entry_heap, ptr);
653 >        mp_pool_release(ptr);
654          ip_entries_count--;
655        }
656        else
# Line 1296 | Line 667 | garbage_collect_ip_entries(void)
667   * side effects - Disassociate configuration from the client.
668   *                Also removes a class from the list if marked for deleting.
669   */
670 < int
671 < detach_conf(struct Client *client_p, ConfType type)
670 > void
671 > detach_conf(struct Client *client_p, enum maskitem_type type)
672   {
673 <  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;
673 >  dlink_node *ptr = NULL, *next_ptr = NULL;
674  
675    DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
676    {
677 <    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);
1317 <
1318 <      switch (conf->type)
1319 <      {
1320 <      case CLIENT_TYPE:
1321 <      case OPER_TYPE:
1322 <      case SERVER_TYPE:
1323 <        aconf = map_to_conf(conf);
677 >    struct MaskItem *conf = ptr->data;
678  
679 <        assert(aconf->clients > 0);
679 >    assert(conf->type & (CONF_CLIENT | CONF_OPER | CONF_SERVER));
680 >    assert(conf->ref_count > 0);
681 >    assert(conf->class->ref_count > 0);
682  
683 <        if ((aclass_conf = ClassPtr(aconf)) != NULL)
684 <        {
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 <        }
1338 <
1339 <        if (--aconf->clients == 0 && IsConfIllegal(aconf))
1340 <          delete_conf_item(conf);
683 >    if (!(conf->type & type))
684 >      continue;
685  
686 <        break;
686 >    dlinkDelete(ptr, &client_p->localClient->confs);
687 >    free_dlink_node(ptr);
688  
689 <      case LEAF_TYPE:
690 <      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 <      }
689 >    if (conf->type == CONF_CLIENT)
690 >      remove_from_cidr_check(&client_p->localClient->ip, conf->class);
691  
692 <      if (type != CONF_TYPE)
693 <        return 0;
692 >    if (--conf->class->ref_count == 0 && conf->class->active == 0)
693 >    {
694 >      class_free(conf->class);
695 >      conf->class = NULL;
696      }
1357  }
697  
698 <  return -1;
698 >    if (--conf->ref_count == 0 && conf->active == 0)
699 >      conf_free(conf);
700 >  }
701   }
702  
703   /* attach_conf()
# Line 1370 | Line 711 | detach_conf(struct Client *client_p, Con
711   *                attachment if there was an old one...
712   */
713   int
714 < attach_conf(struct Client *client_p, struct ConfItem *conf)
714 > attach_conf(struct Client *client_p, struct MaskItem *conf)
715   {
716    if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
717      return 1;
718  
719 <  if (conf->type == CLIENT_TYPE ||
720 <      conf->type == SERVER_TYPE ||
721 <      conf->type == OPER_TYPE)
722 <  {
1382 <    struct AccessItem *aconf = map_to_conf(conf);
1383 <    struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
719 >  if (conf->type == CONF_CLIENT)
720 >    if (cidr_limit_reached(IsConfExemptLimits(conf),
721 >                           &client_p->localClient->ip, conf->class))
722 >      return TOO_MANY;    /* Already at maximum allowed */
723  
724 <    if (IsConfIllegal(aconf))
725 <      return NOT_AUTHORIZED;
1387 <
1388 <    if (conf->type == CLIENT_TYPE)
1389 <      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 <  }
724 >  conf->class->ref_count++;
725 >  conf->ref_count++;
726  
727    dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
728  
# Line 1417 | Line 742 | attach_connect_block(struct Client *clie
742                       const char *host)
743   {
744    dlink_node *ptr;
745 <  struct ConfItem *conf;
1421 <  struct AccessItem *aconf;
745 >  struct MaskItem *conf = NULL;
746  
747    assert(client_p != NULL);
748    assert(host != NULL);
# Line 1429 | Line 753 | attach_connect_block(struct Client *clie
753    DLINK_FOREACH(ptr, server_items.head)
754    {
755      conf = ptr->data;
1432    aconf = map_to_conf(conf);
756  
757 <    if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
757 >    if (match(conf->name, name) || match(conf->host, host))
758        continue;
759  
760      attach_conf(client_p, conf);
# Line 1441 | Line 764 | attach_connect_block(struct Client *clie
764    return 0;
765   }
766  
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
767   /* find_conf_name()
768   *
769   * inputs       - pointer to conf link list to search
# Line 1505 | Line 773 | find_conf_exact(ConfType type, const cha
773   * side effects - find a conf entry which matches the name
774   *                and has the given mask.
775   */
776 < struct ConfItem *
777 < find_conf_name(dlink_list *list, const char *name, ConfType type)
776 > struct MaskItem *
777 > find_conf_name(dlink_list *list, const char *name, enum maskitem_type type)
778   {
779    dlink_node *ptr;
780 <  struct ConfItem* conf;
780 >  struct MaskItem* conf;
781  
782    DLINK_FOREACH(ptr, list->head)
783    {
784      conf = ptr->data;
785 <    
785 >
786      if (conf->type == type)
787      {
788        if (conf->name && (irccmp(conf->name, name) == 0 ||
789 <                         match(conf->name, name)))
789 >                         !match(conf->name, name)))
790        return conf;
791      }
792    }
# Line 1533 | Line 801 | find_conf_name(dlink_list *list, const c
801   * side effects - none
802   */
803   static dlink_list *
804 < map_to_list(ConfType type)
804 > map_to_list(enum maskitem_type type)
805   {
806    switch(type)
807    {
808 <  case RXLINE_TYPE:
1541 <    return(&rxconf_items);
1542 <    break;
1543 <  case XLINE_TYPE:
808 >  case CONF_XLINE:
809      return(&xconf_items);
810      break;
811 <  case ULINE_TYPE:
811 >  case CONF_ULINE:
812      return(&uconf_items);
813      break;
814 <  case NRESV_TYPE:
814 >  case CONF_NRESV:
815      return(&nresv_items);
816      break;
817 <  case OPER_TYPE:
817 >  case CONF_CRESV:
818 >    return(&cresv_items);
819 >  case CONF_OPER:
820      return(&oconf_items);
821      break;
822 <  case CLASS_TYPE:
1556 <    return(&class_items);
1557 <    break;
1558 <  case SERVER_TYPE:
822 >  case CONF_SERVER:
823      return(&server_items);
824      break;
825 <  case SERVICE_TYPE:
825 >  case CONF_SERVICE:
826      return(&service_items);
827      break;
828 <  case CLUSTER_TYPE:
828 >  case CONF_CLUSTER:
829      return(&cluster_items);
830      break;
1567  case CONF_TYPE:
1568  case GLINE_TYPE:
1569  case KLINE_TYPE:
1570  case DLINE_TYPE:
1571  case CRESV_TYPE:
831    default:
832      return NULL;
833    }
# Line 1580 | Line 839 | map_to_list(ConfType type)
839   *              - pointer to name string to find
840   *              - pointer to user
841   *              - pointer to host
842 < *              - optional action to match on as well
843 < * output       - NULL or pointer to found struct MatchItem
842 > *              - optional flags to match on as well
843 > * output       - NULL or pointer to found struct MaskItem
844   * side effects - looks for a match on name field
845   */
846 < struct ConfItem *
847 < find_matching_name_conf(ConfType type, const char *name, const char *user,
848 <                        const char *host, int action)
846 > struct MaskItem *
847 > find_matching_name_conf(enum maskitem_type type, const char *name, const char *user,
848 >                        const char *host, unsigned int flags)
849   {
850    dlink_node *ptr=NULL;
851 <  struct ConfItem *conf=NULL;
1593 <  struct AccessItem *aconf=NULL;
1594 <  struct MatchItem *match_item=NULL;
851 >  struct MaskItem *conf=NULL;
852    dlink_list *list_p = map_to_list(type);
853  
854    switch (type)
855    {
856 < #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:
856 >  case CONF_SERVICE:
857      DLINK_FOREACH(ptr, list_p->head)
858      {
859        conf = ptr->data;
# Line 1620 | Line 865 | find_matching_name_conf(ConfType type, c
865      }
866      break;
867  
868 <  case XLINE_TYPE:
869 <  case ULINE_TYPE:
870 <  case NRESV_TYPE:
868 >  case CONF_XLINE:
869 >  case CONF_ULINE:
870 >  case CONF_NRESV:
871 >  case CONF_CRESV:
872      DLINK_FOREACH(ptr, list_p->head)
873      {
874        conf = ptr->data;
875  
1630      match_item = map_to_conf(conf);
876        if (EmptyString(conf->name))
877 <        continue;
878 <      if ((name != NULL) && match_esc(conf->name, name))
877 >        continue;
878 >      if ((name != NULL) && !match(conf->name, name))
879        {
880 <        if ((user == NULL && (host == NULL)))
881 <          return conf;
882 <        if ((match_item->action & action) != action)
880 >        if ((user == NULL && (host == NULL)))
881 >          return conf;
882 >        if ((conf->flags & flags) != flags)
883            continue;
884 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
885 <          return conf;
886 <        if (match(match_item->user, user) && match(match_item->host, host))
887 <          return conf;
884 >        if (EmptyString(conf->user) || EmptyString(conf->host))
885 >          return conf;
886 >        if (!match(conf->user, user) && !match(conf->host, host))
887 >          return conf;
888        }
889      }
890        break;
891  
892 <  case SERVER_TYPE:
892 >  case CONF_SERVER:
893      DLINK_FOREACH(ptr, list_p->head)
894      {
895        conf = ptr->data;
1651      aconf = map_to_conf(conf);
896  
897 <      if ((name != NULL) && match_esc(name, conf->name))
897 >      if ((name != NULL) && !match(name, conf->name))
898          return conf;
899 <      else if ((host != NULL) && match_esc(host, aconf->host))
899 >      else if ((host != NULL) && !match(host, conf->host))
900          return conf;
901      }
902      break;
903 <  
903 >
904    default:
905      break;
906    }
# Line 1669 | Line 913 | find_matching_name_conf(ConfType type, c
913   *              - pointer to name string to find
914   *              - pointer to user
915   *              - pointer to host
916 < * output       - NULL or pointer to found struct MatchItem
916 > * output       - NULL or pointer to found struct MaskItem
917   * side effects - looks for an exact match on name field
918   */
919 < struct ConfItem *
920 < find_exact_name_conf(ConfType type, const char *name,
919 > struct MaskItem *
920 > find_exact_name_conf(enum maskitem_type type, const struct Client *who, const char *name,
921                       const char *user, const char *host)
922   {
923    dlink_node *ptr = NULL;
924 <  struct AccessItem *aconf;
925 <  struct ConfItem *conf;
1682 <  struct MatchItem *match_item;
1683 <  dlink_list *list_p;
1684 <
1685 <  list_p = map_to_list(type);
924 >  struct MaskItem *conf;
925 >  dlink_list *list_p = map_to_list(type);
926  
927    switch(type)
928    {
929 <  case RXLINE_TYPE:
930 <  case XLINE_TYPE:
931 <  case ULINE_TYPE:
932 <  case NRESV_TYPE:
929 >  case CONF_XLINE:
930 >  case CONF_ULINE:
931 >  case CONF_NRESV:
932 >  case CONF_CRESV:
933  
934      DLINK_FOREACH(ptr, list_p->head)
935      {
936        conf = ptr->data;
937 <      match_item = (struct MatchItem *)map_to_conf(conf);
937 >
938        if (EmptyString(conf->name))
939 <        continue;
940 <    
939 >        continue;
940 >
941        if (irccmp(conf->name, name) == 0)
942        {
943 <        if ((user == NULL && (host == NULL)))
944 <          return (conf);
945 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
946 <          return (conf);
947 <        if (match(match_item->user, user) && match(match_item->host, host))
948 <          return (conf);
943 >        if ((user == NULL && (host == NULL)))
944 >          return conf;
945 >        if (EmptyString(conf->user) || EmptyString(conf->host))
946 >          return conf;
947 >        if (!match(conf->user, user) && !match(conf->host, host))
948 >          return conf;
949        }
950      }
951      break;
952  
953 <  case OPER_TYPE:
953 >  case CONF_OPER:
954      DLINK_FOREACH(ptr, list_p->head)
955      {
956        conf = ptr->data;
957 <      aconf = (struct AccessItem *)map_to_conf(conf);
957 >
958        if (EmptyString(conf->name))
959 <        continue;
960 <    
961 <      if (irccmp(conf->name, name) == 0)
959 >        continue;
960 >
961 >      if (!irccmp(conf->name, name))
962        {
963 <        if ((user == NULL && (host == NULL)))
964 <          return (conf);
965 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
966 <          return (conf);
967 <        if (match(aconf->user, user) && match(aconf->host, host))
968 <          return (conf);
963 >        if (!who)
964 >          return conf;
965 >        if (EmptyString(conf->user) || EmptyString(conf->host))
966 >          return NULL;
967 >        if (!match(conf->user, who->username))
968 >        {
969 >          switch (conf->htype)
970 >          {
971 >            case HM_HOST:
972 >              if (!match(conf->host, who->host) || !match(conf->host, who->sockhost))
973 >                if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
974 >                  return conf;
975 >              break;
976 >            case HM_IPV4:
977 >              if (who->localClient->aftype == AF_INET)
978 >                if (match_ipv4(&who->localClient->ip, &conf->addr, conf->bits))
979 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
980 >                    return conf;
981 >              break;
982 > #ifdef IPV6
983 >            case HM_IPV6:
984 >              if (who->localClient->aftype == AF_INET6)
985 >                if (match_ipv6(&who->localClient->ip, &conf->addr, conf->bits))
986 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
987 >                    return conf;
988 >              break;
989 > #endif
990 >            default:
991 >              assert(0);
992 >          }
993 >        }
994        }
995      }
996 +
997      break;
998  
999 <  case SERVER_TYPE:
999 >  case CONF_SERVER:
1000      DLINK_FOREACH(ptr, list_p->head)
1001      {
1002        conf = ptr->data;
1003 <      aconf = (struct AccessItem *)map_to_conf(conf);
1003 >
1004        if (EmptyString(conf->name))
1005 <        continue;
1006 <    
1005 >        continue;
1006 >
1007        if (name == NULL)
1008        {
1009 <        if (EmptyString(aconf->host))
1010 <          continue;
1011 <        if (irccmp(aconf->host, host) == 0)
1012 <          return(conf);
1009 >        if (EmptyString(conf->host))
1010 >          continue;
1011 >        if (irccmp(conf->host, host) == 0)
1012 >          return conf;
1013        }
1014        else if (irccmp(conf->name, name) == 0)
1015 <      {
1750 <          return (conf);
1751 <      }
1015 >        return conf;
1016      }
1753    break;
1017  
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    }
1018      break;
1019  
1020    default:
1021      break;
1022    }
1023 <  return(NULL);
1023 >
1024 >  return NULL;
1025   }
1026  
1027   /* rehash()
# Line 1780 | Line 1034 | int
1034   rehash(int sig)
1035   {
1036    if (sig != 0)
1037 <    sendto_realops_flags(UMODE_ALL, L_ALL,
1038 <                         "Got signal SIGHUP, reloading ircd.conf file");
1037 >    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1038 >                         "Got signal SIGHUP, reloading configuration file(s)");
1039  
1040    restart_resolver();
1041  
# Line 1797 | Line 1051 | rehash(int sig)
1051  
1052    load_conf_modules();
1053  
1800  flush_deleted_I_P();
1801
1054    rehashed_klines = 1;
1055  
1056 <  if (ConfigLoggingEntry.use_logging)
1805 <    reopen_log(logFileName);
1806 <
1807 <  return(0);
1056 >  return 0;
1057   }
1058  
1059   /* set_default_conf()
# Line 1822 | Line 1071 | set_default_conf(void)
1071    /* verify init_class() ran, this should be an unnecessary check
1072     * but its not much work.
1073     */
1074 <  assert(class_default == (struct ConfItem *) class_items.tail->data);
1074 >  assert(class_default == class_get_list()->tail->data);
1075  
1076   #ifdef HAVE_LIBCRYPTO
1077    ServerInfo.rsa_private_key = NULL;
# Line 1832 | Line 1081 | set_default_conf(void)
1081    /* ServerInfo.name is not rehashable */
1082    /* ServerInfo.name = ServerInfo.name; */
1083    ServerInfo.description = NULL;
1084 <  DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1085 <  DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1084 >  ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1085 >  ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1086  
1087    memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1088    ServerInfo.specific_ipv4_vhost = 0;
# Line 1841 | Line 1090 | set_default_conf(void)
1090    ServerInfo.specific_ipv6_vhost = 0;
1091  
1092    ServerInfo.max_clients = MAXCLIENTS_MAX;
1093 +  ServerInfo.max_nick_length = 9;
1094 +  ServerInfo.max_topic_length = 80;
1095  
1096    ServerInfo.hub = 0;
1097    ServerInfo.dns_host.sin_addr.s_addr = 0;
# Line 1849 | Line 1100 | set_default_conf(void)
1100    AdminInfo.email = NULL;
1101    AdminInfo.description = NULL;
1102  
1103 <  set_log_level(L_NOTICE);
1103 >  log_del_all();
1104 >
1105    ConfigLoggingEntry.use_logging = 1;
1854  ConfigLoggingEntry.operlog[0] = '\0';
1855  ConfigLoggingEntry.userlog[0] = '\0';
1856  ConfigLoggingEntry.klinelog[0] = '\0';
1857  ConfigLoggingEntry.glinelog[0] = '\0';
1858  ConfigLoggingEntry.killlog[0] = '\0';
1859  ConfigLoggingEntry.operspylog[0] = '\0';
1860  ConfigLoggingEntry.ioerrlog[0] = '\0';
1861  ConfigLoggingEntry.failed_operlog[0] = '\0';
1106  
1107    ConfigChannel.disable_fake_channels = 0;
1864  ConfigChannel.restrict_channels = 0;
1865  ConfigChannel.disable_local_channels = 0;
1866  ConfigChannel.use_invex = 1;
1867  ConfigChannel.use_except = 1;
1868  ConfigChannel.use_knock = 1;
1108    ConfigChannel.knock_delay = 300;
1109    ConfigChannel.knock_delay_channel = 60;
1110 <  ConfigChannel.max_chans_per_user = 15;
1111 <  ConfigChannel.quiet_on_ban = 1;
1110 >  ConfigChannel.max_chans_per_user = 25;
1111 >  ConfigChannel.max_chans_per_oper = 50;
1112    ConfigChannel.max_bans = 25;
1113    ConfigChannel.default_split_user_count = 0;
1114    ConfigChannel.default_split_server_count = 0;
1115    ConfigChannel.no_join_on_split = 0;
1116    ConfigChannel.no_create_on_split = 0;
1878  ConfigChannel.burst_topicwho = 1;
1117  
1118    ConfigServerHide.flatten_links = 0;
1119    ConfigServerHide.links_delay = 300;
1120    ConfigServerHide.hidden = 0;
1883  ConfigServerHide.disable_hidden = 0;
1121    ConfigServerHide.hide_servers = 0;
1122 <  DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1122 >  ConfigServerHide.hide_services = 0;
1123 >  ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
1124    ConfigServerHide.hide_server_ips = 0;
1125 +  ConfigServerHide.disable_remote_commands = 0;
1126  
1127 <  
1889 <  DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1127 >  ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1128    ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1129 +  ConfigFileEntry.cycle_on_host_change = 1;
1130 +  ConfigFileEntry.glines = 0;
1131 +  ConfigFileEntry.gline_time = 12 * 3600;
1132 +  ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
1133    ConfigFileEntry.gline_min_cidr = 16;
1134    ConfigFileEntry.gline_min_cidr6 = 48;
1135    ConfigFileEntry.invisible_on_connect = 1;
1894  ConfigFileEntry.burst_away = 0;
1895  ConfigFileEntry.use_whois_actually = 1;
1136    ConfigFileEntry.tkline_expire_notices = 1;
1137    ConfigFileEntry.hide_spoof_ips = 1;
1138    ConfigFileEntry.ignore_bogus_ts = 0;
1139    ConfigFileEntry.disable_auth = 0;
1900  ConfigFileEntry.disable_remote = 0;
1140    ConfigFileEntry.kill_chase_time_limit = 90;
1141    ConfigFileEntry.default_floodcount = 8;
1142    ConfigFileEntry.failed_oper_notice = 1;
# Line 1911 | Line 1150 | set_default_conf(void)
1150    ConfigFileEntry.anti_spam_exit_message_time = 0;
1151    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1152    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1914  ConfigFileEntry.kline_with_reason = 1;
1915  ConfigFileEntry.kline_reason = NULL;
1153    ConfigFileEntry.warn_no_nline = 1;
1154    ConfigFileEntry.stats_o_oper_only = 0;
1155    ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
1156    ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
1157    ConfigFileEntry.stats_P_oper_only = 0;
1158 +  ConfigFileEntry.stats_u_oper_only = 0;
1159    ConfigFileEntry.caller_id_wait = 60;
1160    ConfigFileEntry.opers_bypass_callerid = 0;
1161    ConfigFileEntry.pace_wait = 10;
# Line 1927 | Line 1165 | set_default_conf(void)
1165    ConfigFileEntry.no_oper_flood = 0;
1166    ConfigFileEntry.true_no_oper_flood = 0;
1167    ConfigFileEntry.oper_pass_resv = 1;
1930  ConfigFileEntry.glines = 0;
1931  ConfigFileEntry.gline_time = 12 * 3600;
1168    ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1933  ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1169    ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1170    ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1171      UMODE_OPERWALL | UMODE_WALLOP;
1937  DupString(ConfigFileEntry.servlink_path, SLPATH);
1938 #ifdef HAVE_LIBCRYPTO
1939  /* jdc -- This is our default value for a cipher.  According to the
1940   *        CRYPTLINK document (doc/cryptlink.txt), BF/128 must be supported
1941   *        under all circumstances if cryptlinks are enabled.  So,
1942   *        this will be our default.
1943   *
1944   *        NOTE: I apologise for the hard-coded value of "1" (BF/128).
1945   *              This should be moved into a find_cipher() routine.
1946   */
1947  ConfigFileEntry.default_cipher_preference = &CipherTable[1];
1948 #endif
1172    ConfigFileEntry.use_egd = 0;
1173    ConfigFileEntry.egdpool_path = NULL;
1951 #ifdef HAVE_LIBZ
1952  ConfigFileEntry.compression_level = 0;
1953 #endif
1174    ConfigFileEntry.throttle_time = 10;
1175   }
1176  
1177 < /* read_conf()
1177 > static void
1178 > validate_conf(void)
1179 > {
1180 >  if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1181 >    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1182 >
1183 >  if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1184 >    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1185 >
1186 >  if (ServerInfo.network_name == NULL)
1187 >    ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1188 >
1189 >  if (ServerInfo.network_desc == NULL)
1190 >    ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1191 >
1192 >  if (ConfigFileEntry.service_name == NULL)
1193 >    ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1194 >
1195 >  ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1196 > }
1197 >
1198 > /* read_conf()
1199   *
1200   * inputs       - file descriptor pointing to config file to use
1201   * output       - None
1202   * side effects - Read configuration file.
1203   */
1204   static void
1205 < read_conf(FBFILE *file)
1205 > read_conf(FILE *file)
1206   {
1207    lineno = 0;
1208  
1209    set_default_conf(); /* Set default values prior to conf parsing */
1210    conf_parser_ctx.pass = 1;
1211 <  yyparse();          /* pick up the classes first */
1211 >  yyparse();          /* pick up the classes first */
1212  
1213 <  fbrewind(file);
1213 >  rewind(file);
1214  
1215    conf_parser_ctx.pass = 2;
1216    yyparse();          /* Load the values from the conf */
1217    validate_conf();    /* Check to make sure some values are still okay. */
1218                        /* Some global values are also loaded here. */
1219 <  check_class();      /* Make sure classes are valid */
1979 < }
1980 <
1981 < static void
1982 < validate_conf(void)
1983 < {
1984 <  if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1985 <    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1986 <
1987 <  if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1988 <    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1989 <
1990 <  if (ConfigFileEntry.servlink_path == NULL)
1991 <    DupString(ConfigFileEntry.servlink_path, SLPATH);
1992 <
1993 <  if (ServerInfo.network_name == NULL)
1994 <    DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1995 <
1996 <  if (ServerInfo.network_desc == NULL)
1997 <    DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1998 <
1999 <  if (ConfigFileEntry.service_name == NULL)
2000 <    DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
2001 <
2002 <  if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
2003 <      (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
2004 <    ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
2005 <
2006 <  ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1219 >  class_delete_marked();      /* Make sure classes are valid */
1220   }
1221  
1222   /* lookup_confhost()
# Line 2011 | Line 1224 | validate_conf(void)
1224   * start DNS lookups of all hostnames in the conf
1225   * line and convert an IP addresses in a.b.c.d number for to IP#s.
1226   */
1227 < static void
1228 < lookup_confhost(struct ConfItem *conf)
1227 > void
1228 > lookup_confhost(struct MaskItem *conf)
1229   {
2017  struct AccessItem *aconf;
1230    struct addrinfo hints, *res;
1231  
2020  aconf = map_to_conf(conf);
2021
2022  if (EmptyString(aconf->host) ||
2023      EmptyString(aconf->user))
2024  {
2025    ilog(L_ERROR, "Host/server name error: (%s) (%s)",
2026         aconf->host, conf->name);
2027    return;
2028  }
2029
2030  if (strchr(aconf->host, '*') ||
2031      strchr(aconf->host, '?'))
2032    return;
2033
1232    /* Do name lookup now on hostnames given and store the
1233     * ip numbers in conf structure.
1234     */
# Line 2042 | Line 1240 | lookup_confhost(struct ConfItem *conf)
1240    /* Get us ready for a bind() and don't bother doing dns lookup */
1241    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1242  
1243 <  if (getaddrinfo(aconf->host, NULL, &hints, &res))
1243 >  if (getaddrinfo(conf->host, NULL, &hints, &res))
1244    {
1245 <    conf_dns_lookup(aconf);
1245 >    conf_dns_lookup(conf);
1246      return;
1247    }
1248  
1249    assert(res != NULL);
1250  
1251 <  memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
1252 <  aconf->ipnum.ss_len = res->ai_addrlen;
1253 <  aconf->ipnum.ss.ss_family = res->ai_family;
1251 >  memcpy(&conf->addr, res->ai_addr, res->ai_addrlen);
1252 >  conf->addr.ss_len = res->ai_addrlen;
1253 >  conf->addr.ss.ss_family = res->ai_family;
1254 >
1255    freeaddrinfo(res);
1256   }
1257  
# Line 2067 | Line 1266 | int
1266   conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1267   {
1268    struct ip_entry *ip_found;
1269 <  struct AccessItem *aconf = find_dline_conf(addr, aftype);
1269 >  struct MaskItem *conf = find_dline_conf(addr, aftype);
1270  
1271    /* DLINE exempt also gets you out of static limits/pacing... */
1272 <  if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1272 >  if (conf && (conf->type == CONF_EXEMPT))
1273      return 0;
1274  
1275 <  if (aconf != NULL)
1275 >  if (conf != NULL)
1276      return BANNED_CLIENT;
1277  
1278    ip_found = find_or_add_ip(addr);
# Line 2089 | Line 1288 | conf_connect_allowed(struct irc_ssaddr *
1288    return 0;
1289   }
1290  
2092 static struct AccessItem *
2093 find_regexp_kline(const char *uhi[])
2094 {
2095 #ifdef HAVE_LIBPCRE
2096  const dlink_node *ptr = NULL;
2097
2098  DLINK_FOREACH(ptr, rkconf_items.head)
2099  {
2100    struct AccessItem *aptr = map_to_conf(ptr->data);
2101
2102    assert(aptr->regexuser);
2103    assert(aptr->regexhost);
2104
2105    if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2106        (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2107         !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2108      return aptr;
2109  }
2110 #endif
2111  return NULL;
2112 }
2113
2114 /* find_kill()
2115 *
2116 * inputs       - pointer to client structure
2117 * output       - pointer to struct AccessItem if found
2118 * side effects - See if this user is klined already,
2119 *                and if so, return struct AccessItem pointer
2120 */
2121 struct AccessItem *
2122 find_kill(struct Client *client_p)
2123 {
2124  struct AccessItem *aconf = NULL;
2125  const char *uhi[3];
2126
2127  uhi[0] = client_p->username;
2128  uhi[1] = client_p->host;
2129  uhi[2] = client_p->sockhost;
2130
2131  assert(client_p != NULL);
2132
2133  aconf = find_kline_conf(client_p->host, client_p->username,
2134                          &client_p->localClient->ip,
2135                          client_p->localClient->aftype);
2136  if (aconf == NULL)
2137    aconf = find_regexp_kline(uhi);
2138
2139  if (aconf && (aconf->status & CONF_KLINE))
2140    return aconf;
2141
2142  return NULL;
2143 }
2144
2145 struct AccessItem *
2146 find_gline(struct Client *client_p)
2147 {
2148  struct AccessItem *aconf;
2149
2150  assert(client_p != NULL);
2151
2152  aconf = find_gline_conf(client_p->host, client_p->username,
2153                          &client_p->localClient->ip,
2154                          client_p->localClient->aftype);
2155
2156  if (aconf && (aconf->status & CONF_GLINE))
2157    return aconf;
2158
2159  return NULL;
2160 }
2161
2162 /* add_temp_line()
2163 *
2164 * inputs        - pointer to struct ConfItem
2165 * output        - none
2166 * Side effects  - links in given struct ConfItem into
2167 *                 temporary *line link list
2168 */
2169 void
2170 add_temp_line(struct ConfItem *conf)
2171 {
2172  struct AccessItem *aconf;
2173
2174  if (conf->type == DLINE_TYPE)
2175  {
2176    aconf = map_to_conf(conf);
2177    SetConfTemporary(aconf);
2178    dlinkAdd(conf, &conf->node, &temporary_dlines);
2179    MyFree(aconf->user);
2180    aconf->user = NULL;
2181    add_conf_by_address(CONF_DLINE, aconf);
2182  }
2183  else if (conf->type == KLINE_TYPE)
2184  {
2185    aconf = map_to_conf(conf);
2186    SetConfTemporary(aconf);
2187    dlinkAdd(conf, &conf->node, &temporary_klines);
2188    add_conf_by_address(CONF_KILL, aconf);
2189  }
2190  else if (conf->type == GLINE_TYPE)
2191  {
2192    aconf = map_to_conf(conf);
2193    SetConfTemporary(aconf);
2194    dlinkAdd(conf, &conf->node, &temporary_glines);
2195    add_conf_by_address(CONF_GLINE, aconf);
2196  }
2197  else if (conf->type == XLINE_TYPE)
2198  {
2199    conf->flags |= CONF_FLAGS_TEMPORARY;
2200    dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2201  }
2202  else if (conf->type == RXLINE_TYPE)
2203  {
2204    conf->flags |= CONF_FLAGS_TEMPORARY;
2205    dlinkAdd(conf, make_dlink_node(), &temporary_rxlines);
2206  }
2207  else if (conf->type == RKLINE_TYPE)
2208  {
2209    conf->flags |= CONF_FLAGS_TEMPORARY;
2210    dlinkAdd(conf, make_dlink_node(), &temporary_rklines);
2211  }
2212  else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2213  {
2214    conf->flags |= CONF_FLAGS_TEMPORARY;
2215    dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2216  }
2217 }
2218
1291   /* cleanup_tklines()
1292   *
1293   * inputs       - NONE
# Line 2226 | Line 1298 | add_temp_line(struct ConfItem *conf)
1298   void
1299   cleanup_tklines(void *notused)
1300   {
1301 <  expire_tklines(&temporary_glines);
1302 <  expire_tklines(&temporary_klines);
1303 <  expire_tklines(&temporary_dlines);
1304 <  expire_tklines(&temporary_xlines);
2233 <  expire_tklines(&temporary_rxlines);
2234 <  expire_tklines(&temporary_rklines);
2235 <  expire_tklines(&temporary_resv);
1301 >  hostmask_expire_temporary();
1302 >  expire_tklines(&xconf_items);
1303 >  expire_tklines(&nresv_items);
1304 >  expire_tklines(&cresv_items);
1305   }
1306  
1307   /* expire_tklines()
# Line 2246 | Line 1315 | expire_tklines(dlink_list *tklist)
1315   {
1316    dlink_node *ptr;
1317    dlink_node *next_ptr;
1318 <  struct ConfItem *conf;
2250 <  struct MatchItem *xconf;
2251 <  struct MatchItem *nconf;
2252 <  struct AccessItem *aconf;
2253 <  struct ResvChannel *cconf;
1318 >  struct MaskItem *conf;
1319  
1320    DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
1321    {
1322      conf = ptr->data;
2258    if (conf->type == GLINE_TYPE ||
2259        conf->type == KLINE_TYPE ||
2260        conf->type == DLINE_TYPE)
2261    {
2262      aconf = (struct AccessItem *)map_to_conf(conf);
2263      if (aconf->hold <= CurrentTime)
2264      {
2265        /* XXX - Do we want GLINE expiry notices?? */
2266        /* Alert opers that a TKline expired - Hwy */
2267        if (ConfigFileEntry.tkline_expire_notices)
2268        {
2269          if (aconf->status & CONF_KILL)
2270          {
2271            sendto_realops_flags(UMODE_ALL, L_ALL,
2272                                 "Temporary K-line for [%s@%s] expired",
2273                                 (aconf->user) ? aconf->user : "*",
2274                                 (aconf->host) ? aconf->host : "*");
2275          }
2276          else if (conf->type == DLINE_TYPE)
2277          {
2278            sendto_realops_flags(UMODE_ALL, L_ALL,
2279                                 "Temporary D-line for [%s] expired",
2280                                 (aconf->host) ? aconf->host : "*");
2281          }
2282        }
1323  
1324 <        dlinkDelete(ptr, tklist);
1325 <        delete_one_address_conf(aconf->host, aconf);
1326 <      }
1327 <    }
2288 <    else if (conf->type == XLINE_TYPE ||
2289 <             conf->type == RXLINE_TYPE)
2290 <    {
2291 <      xconf = (struct MatchItem *)map_to_conf(conf);
2292 <      if (xconf->hold <= CurrentTime)
2293 <      {
2294 <        if (ConfigFileEntry.tkline_expire_notices)
2295 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2296 <                               "Temporary X-line for [%s] %sexpired", conf->name,
2297 <                               conf->type == RXLINE_TYPE ? "(REGEX) " : "");
2298 <        dlinkDelete(ptr, tklist);
2299 <        free_dlink_node(ptr);
2300 <        delete_conf_item(conf);
2301 <      }
2302 <    }
2303 <    else if (conf->type == RKLINE_TYPE)
1324 >    if (!conf->until || conf->until > CurrentTime)
1325 >      continue;
1326 >
1327 >    if (conf->type == CONF_XLINE)
1328      {
1329 <      aconf = map_to_conf(conf);
1330 <      if (aconf->hold <= CurrentTime)
1331 <      {
1332 <        if (ConfigFileEntry.tkline_expire_notices)
2309 <           sendto_realops_flags(UMODE_ALL, L_ALL,
2310 <                                "Temporary K-line for [%s@%s] (REGEX) expired",
2311 <                                (aconf->user) ? aconf->user : "*",
2312 <                                (aconf->host) ? aconf->host : "*");
2313 <        dlinkDelete(ptr, tklist);
2314 <        free_dlink_node(ptr);
2315 <        delete_conf_item(conf);
2316 <      }
1329 >      if (ConfigFileEntry.tkline_expire_notices)
1330 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1331 >                               "Temporary X-line for [%s] expired", conf->name);
1332 >      conf_free(conf);
1333      }
1334 <    else if (conf->type == NRESV_TYPE)
1334 >    else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1335      {
1336 <      nconf = (struct MatchItem *)map_to_conf(conf);
1337 <      if (nconf->hold <= CurrentTime)
2322 <      {
2323 <        if (ConfigFileEntry.tkline_expire_notices)
2324 <          sendto_realops_flags(UMODE_ALL, L_ALL,
1336 >      if (ConfigFileEntry.tkline_expire_notices)
1337 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1338                                 "Temporary RESV for [%s] expired", conf->name);
1339 <        dlinkDelete(ptr, tklist);
2327 <        free_dlink_node(ptr);
2328 <        delete_conf_item(conf);
2329 <      }
2330 <    }
2331 <    else if (conf->type == CRESV_TYPE)
2332 <    {
2333 <      cconf = (struct ResvChannel *)map_to_conf(conf);
2334 <      if (cconf->hold <= CurrentTime)
2335 <      {
2336 <        if (ConfigFileEntry.tkline_expire_notices)
2337 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2338 <                               "Temporary RESV for [%s] expired", cconf->name);
2339 <        delete_channel_resv(cconf);
2340 <      }
1339 >      conf_free(conf);
1340      }
1341    }
1342   }
# Line 2350 | Line 1349 | expire_tklines(dlink_list *tklist)
1349   */
1350   static const struct oper_privs
1351   {
1352 <  const unsigned int oprivs;
2354 <  const unsigned int hidden;
1352 >  const unsigned int flag;
1353    const unsigned char c;
1354   } flag_list[] = {
1355 <  { OPER_FLAG_ADMIN,       OPER_FLAG_HIDDEN_ADMIN,  'A' },
1356 <  { OPER_FLAG_REMOTEBAN,   0,                       'B' },
1357 <  { OPER_FLAG_DIE,         0,                       'D' },
1358 <  { OPER_FLAG_GLINE,       0,                       'G' },
1359 <  { OPER_FLAG_REHASH,      0,                       'H' },
1360 <  { OPER_FLAG_K,           0,                       'K' },
1361 <  { OPER_FLAG_OPERWALL,    0,                       'L' },
1362 <  { OPER_FLAG_N,           0,                       'N' },
1363 <  { OPER_FLAG_GLOBAL_KILL, 0,                       'O' },
1364 <  { OPER_FLAG_REMOTE,      0,                       'R' },
1365 <  { OPER_FLAG_OPER_SPY,    0,                       'S' },
1366 <  { OPER_FLAG_UNKLINE,     0,                       'U' },
1367 <  { OPER_FLAG_X,           0,                       'X' },
1368 <  { 0, 0, '\0' }
1355 >  { OPER_FLAG_ADMIN,          'A' },
1356 >  { OPER_FLAG_REMOTEBAN,      'B' },
1357 >  { OPER_FLAG_DIE,            'D' },
1358 >  { OPER_FLAG_GLINE,          'G' },
1359 >  { OPER_FLAG_REHASH,         'H' },
1360 >  { OPER_FLAG_K,              'K' },
1361 >  { OPER_FLAG_OPERWALL,       'L' },
1362 >  { OPER_FLAG_KILL,           'N' },
1363 >  { OPER_FLAG_KILL_REMOTE,    'O' },
1364 >  { OPER_FLAG_CONNECT,        'P' },
1365 >  { OPER_FLAG_CONNECT_REMOTE, 'Q' },
1366 >  { OPER_FLAG_SQUIT,          'R' },
1367 >  { OPER_FLAG_SQUIT_REMOTE,   'S' },
1368 >  { OPER_FLAG_UNKLINE,        'U' },
1369 >  { OPER_FLAG_XLINE,          'X' },
1370 >  { 0, '\0' }
1371   };
1372  
1373   char *
1374   oper_privs_as_string(const unsigned int port)
1375   {
1376 <  static char privs_out[16];
1376 >  static char privs_out[IRCD_BUFSIZE];
1377    char *privs_ptr = privs_out;
1378 <  unsigned int i = 0;
1378 >  const struct oper_privs *opriv = flag_list;
1379  
1380 <  for (; flag_list[i].oprivs; ++i)
1380 >  for (; opriv->flag; ++opriv)
1381    {
1382 <    if ((port & flag_list[i].oprivs) &&
1383 <        (port & flag_list[i].hidden) == 0)
2384 <      *privs_ptr++ = flag_list[i].c;
1382 >    if (port & opriv->flag)
1383 >      *privs_ptr++ = opriv->c;
1384      else
1385 <      *privs_ptr++ = ToLowerTab[flag_list[i].c];
1385 >      *privs_ptr++ = ToLower(opriv->c);
1386    }
1387  
1388    *privs_ptr = '\0';
# Line 2397 | Line 1396 | oper_privs_as_string(const unsigned int
1396   *         "oper" is server name for remote opers
1397   * Side effects: None.
1398   */
1399 < char *
1399 > const char *
1400   get_oper_name(const struct Client *client_p)
1401   {
1402 <  dlink_node *cnode;
2404 <  struct ConfItem *conf;
2405 <  struct AccessItem *aconf;
2406 <
1402 >  const dlink_node *cnode = NULL;
1403    /* +5 for !,@,{,} and null */
1404    static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
1405  
1406    if (MyConnect(client_p))
1407    {
1408 <    DLINK_FOREACH(cnode, client_p->localClient->confs.head)
1408 >    if ((cnode = client_p->localClient->confs.head))
1409      {
1410 <      conf = cnode->data;
2415 <      aconf = map_to_conf(conf);
1410 >      const struct MaskItem *conf = cnode->data;
1411  
1412 <      if (IsConfOperator(aconf))
1412 >      if (IsConfOperator(conf))
1413        {
1414 <        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1414 >        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1415                   client_p->username, client_p->host, conf->name);
1416 <        return buffer;
1416 >        return buffer;
1417        }
1418      }
1419  
1420 <    /* Probably should assert here for now. If there is an oper out there
1420 >    /* Probably should assert here for now. If there is an oper out there
1421       * with no oper{} conf attached, it would be good for us to know...
1422       */
1423      assert(0); /* Oper without oper conf! */
1424    }
1425  
1426    snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1427 <           client_p->username, client_p->host, client_p->servptr->name);
1427 >           client_p->username, client_p->host, client_p->servptr->name);
1428    return buffer;
1429   }
1430  
# Line 2443 | Line 1438 | void
1438   read_conf_files(int cold)
1439   {
1440    const char *filename;
1441 <  char chanmodes[32];
1442 <  char chanlimit[32];
1441 >  char chanmodes[IRCD_BUFSIZE];
1442 >  char chanlimit[IRCD_BUFSIZE];
1443  
1444    conf_parser_ctx.boot = cold;
1445 <  filename = get_conf_name(CONF_TYPE);
1445 >  filename = ConfigFileEntry.configfile;
1446  
1447    /* We need to know the initial filename for the yyerror() to report
1448       FIXME: The full path is in conffilenamebuf first time since we
1449               dont know anything else
1450  
1451 <     - Gozem 2002-07-21
1451 >     - Gozem 2002-07-21
1452    */
1453    strlcpy(conffilebuf, filename, sizeof(conffilebuf));
1454  
1455 <  if ((conf_parser_ctx.conf_file = fbopen(filename, "r")) == NULL)
1455 >  if ((conf_parser_ctx.conf_file = fopen(filename, "r")) == NULL)
1456    {
1457      if (cold)
1458      {
1459 <      ilog(L_CRIT, "Unable to read configuration file '%s': %s",
1459 >      ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
1460             filename, strerror(errno));
1461        exit(-1);
1462      }
1463      else
1464      {
1465 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1466 <                           "Unable to read configuration file '%s': %s",
1467 <                           filename, strerror(errno));
1465 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1466 >                           "Unable to read configuration file '%s': %s",
1467 >                           filename, strerror(errno));
1468        return;
1469      }
1470    }
# Line 2478 | Line 1473 | read_conf_files(int cold)
1473      clear_out_old_conf();
1474  
1475    read_conf(conf_parser_ctx.conf_file);
1476 <  fbclose(conf_parser_ctx.conf_file);
1476 >  fclose(conf_parser_ctx.conf_file);
1477 >
1478 >  log_reopen_all();
1479  
1480 +  add_isupport("NICKLEN", NULL, ServerInfo.max_nick_length);
1481    add_isupport("NETWORK", ServerInfo.network_name, -1);
1482 <  snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
1483 <           ConfigChannel.use_except ? "e" : "",
2486 <           ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
1482 >
1483 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1484    add_isupport("MAXLIST", chanmodes, -1);
1485    add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1486 +  add_isupport("CHANTYPES", "#", -1);
1487  
1488 <  if (ConfigChannel.disable_local_channels)
1489 <    add_isupport("CHANTYPES", "#", -1);
2492 <  else
2493 <    add_isupport("CHANTYPES", "#&", -1);
2494 <
2495 <  snprintf(chanlimit, sizeof(chanlimit), "%s:%d",
2496 <           ConfigChannel.disable_local_channels ? "#" : "#&",
2497 <           ConfigChannel.max_chans_per_user);
1488 >  snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1489 >           ConfigChannel.max_chans_per_user);
1490    add_isupport("CHANLIMIT", chanlimit, -1);
1491 <  snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
2500 <           ConfigChannel.use_except ? "e" : "",
2501 <           ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
1491 >  snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,imnprstORS");
1492    add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
1493 <
2504 <  if (ConfigChannel.use_except)
2505 <    add_isupport("EXCEPTS", "e", -1);
2506 <  if (ConfigChannel.use_invex)
2507 <    add_isupport("INVEX", "I", -1);
1493 >  add_isupport("TOPICLEN", NULL, ServerInfo.max_topic_length);
1494    add_isupport("CHANMODES", chanmodes, -1);
1495  
1496    /*
# Line 2512 | Line 1498 | read_conf_files(int cold)
1498     * on strlen(form_str(RPL_ISUPPORT))
1499     */
1500    rebuild_isupport_message_line();
2515
2516 #ifdef HAVE_LIBPCRE
2517  parse_conf_file(RKLINE_TYPE, cold);
2518  parse_conf_file(RXLINE_TYPE, cold);
2519 #endif
2520  parse_conf_file(KLINE_TYPE, cold);
2521  parse_conf_file(DLINE_TYPE, cold);
2522  parse_conf_file(XLINE_TYPE, cold);
2523  parse_conf_file(NRESV_TYPE, cold);
2524  parse_conf_file(CRESV_TYPE, cold);
2525 }
2526
2527 /* parse_conf_file()
2528 *
2529 * inputs       - type of conf file to parse
2530 * output       - none
2531 * side effects - conf file for givenconf type is opened and read then parsed
2532 */
2533 static void
2534 parse_conf_file(int type, int cold)
2535 {
2536  FBFILE *file = NULL;
2537  const char *filename = get_conf_name(type);
2538
2539  if ((file = fbopen(filename, "r")) == NULL)
2540  {
2541    if (cold)
2542      ilog(L_ERROR, "Unable to read configuration file '%s': %s",
2543           filename, strerror(errno));
2544    else
2545      sendto_realops_flags(UMODE_ALL, L_ALL,
2546                    "Unable to read configuration file '%s': %s",
2547                           filename, strerror(errno));
2548  }
2549  else
2550  {
2551    parse_csv_file(file, type);
2552    fbclose(file);
2553  }
1501   }
1502  
1503   /* clear_out_old_conf()
# Line 2563 | Line 1510 | static void
1510   clear_out_old_conf(void)
1511   {
1512    dlink_node *ptr = NULL, *next_ptr = NULL;
1513 <  struct ConfItem *conf;
2567 <  struct AccessItem *aconf;
2568 <  struct ClassItem *cltmp;
2569 <  struct MatchItem *match_item;
1513 >  struct MaskItem *conf;
1514    dlink_list *free_items [] = {
1515 <    &server_items,   &oconf_items,    &hub_items, &leaf_items,
1516 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1517 <     &nresv_items, &cluster_items,  &gdeny_items, &service_items, NULL
1515 >    &server_items,   &oconf_items,
1516 >     &uconf_items,   &xconf_items,
1517 >     &nresv_items, &cluster_items,  &service_items, &cresv_items, NULL
1518    };
1519  
1520    dlink_list ** iterator = free_items; /* C is dumb */
# Line 2578 | Line 1522 | clear_out_old_conf(void)
1522    /* We only need to free anything allocated by yyparse() here.
1523     * Resetting structs, etc, is taken care of by set_default_conf().
1524     */
1525 <  
1525 >
1526    for (; *iterator != NULL; iterator++)
1527    {
1528      DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1529      {
1530        conf = ptr->data;
2587      /* XXX This is less than pretty */
2588      if (conf->type == SERVER_TYPE)
2589      {
2590        aconf = map_to_conf(conf);
1531  
1532 <        if (aconf->clients != 0)
2593 <        {
2594 <          SetConfIllegal(aconf);
2595 <          dlinkDelete(&conf->node, &server_items);
2596 <        }
2597 <        else
2598 <        {
2599 <          delete_conf_item(conf);
2600 <        }
2601 <      }
2602 <      else if (conf->type == OPER_TYPE)
2603 <      {
2604 <        aconf = map_to_conf(conf);
1532 >      dlinkDelete(&conf->node, map_to_list(conf->type));
1533  
1534 <        if (aconf->clients != 0)
1535 <        {
2608 <          SetConfIllegal(aconf);
2609 <          dlinkDelete(&conf->node, &oconf_items);
2610 <        }
2611 <        else
2612 <        {
2613 <          delete_conf_item(conf);
2614 <        }
2615 <      }
2616 <      else if (conf->type == CLIENT_TYPE)
1534 >      /* XXX This is less than pretty */
1535 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1536        {
1537 <        aconf = map_to_conf(conf);
1538 <
2620 <        if (aconf->clients != 0)
2621 <        {
2622 <          SetConfIllegal(aconf);
2623 <        }
2624 <        else
2625 <        {
2626 <          delete_conf_item(conf);
2627 <        }
1537 >        if (!conf->ref_count)
1538 >          conf_free(conf);
1539        }
1540 <      else if (conf->type == XLINE_TYPE  ||
2630 <               conf->type == RXLINE_TYPE ||
2631 <               conf->type == RKLINE_TYPE)
1540 >      else if (conf->type == CONF_XLINE)
1541        {
1542 <        /* temporary (r)xlines are also on
1543 <         * the (r)xconf items list */
2635 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2636 <          continue;
2637 <
2638 <        delete_conf_item(conf);
1542 >        if (!conf->until)
1543 >          conf_free(conf);
1544        }
1545        else
1546 <      {
2642 <        if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2643 <        {
2644 <          match_item = map_to_conf(conf);
2645 <          if (match_item->ref_count <= 0)
2646 <            delete_conf_item(conf);
2647 <          else
2648 <          {
2649 <            match_item->illegal = 1;
2650 <            dlinkDelete(&conf->node, *iterator);
2651 <          }
2652 <        }
2653 <        else
2654 <          delete_conf_item(conf);
2655 <      }
1546 >        conf_free(conf);
1547      }
1548    }
1549  
1550 +  motd_clear();
1551 +
1552    /*
1553     * don't delete the class table, rather mark all entries
1554 <   * for deletion. The table is cleaned up by check_class. - avalon
1554 >   * for deletion. The table is cleaned up by class_delete_marked. - avalon
1555     */
1556 <  DLINK_FOREACH(ptr, class_items.head)
2664 <  {
2665 <    cltmp = map_to_conf(ptr->data);
2666 <
2667 <    if (ptr != class_items.tail)  /* never mark the "default" class */
2668 <      cltmp->active = 0;
2669 <  }
1556 >  class_mark_for_deletion();
1557  
1558    clear_out_address_conf();
1559  
# Line 2691 | Line 1578 | clear_out_old_conf(void)
1578  
1579    MyFree(ServerInfo.rsa_private_key_file);
1580    ServerInfo.rsa_private_key_file = NULL;
2694 #endif
1581  
1582 <  /* clean out old resvs from the conf */
1583 <  clear_conf_resv();
1582 >  if (ServerInfo.server_ctx)
1583 >    SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
1584 >                                               SSL_OP_NO_SSLv3|
1585 >                                               SSL_OP_NO_TLSv1);
1586 >  if (ServerInfo.client_ctx)
1587 >    SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
1588 >                                               SSL_OP_NO_SSLv3|
1589 >                                               SSL_OP_NO_TLSv1);
1590 > #endif
1591  
1592    /* clean out AdminInfo */
1593    MyFree(AdminInfo.name);
# Line 2704 | Line 1597 | clear_out_old_conf(void)
1597    MyFree(AdminInfo.description);
1598    AdminInfo.description = NULL;
1599  
2707  /* operator{} and class{} blocks are freed above */
1600    /* clean out listeners */
1601    close_listeners();
1602  
2711  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2712   * exempt{} and gecos{} blocks are freed above too
2713   */
2714
1603    /* clean out general */
1604    MyFree(ConfigFileEntry.service_name);
1605    ConfigFileEntry.service_name = NULL;
2718
2719  MyFree(ConfigFileEntry.servlink_path);
2720  ConfigFileEntry.servlink_path = NULL;
2721 #ifdef HAVE_LIBCRYPTO
2722  ConfigFileEntry.default_cipher_preference = NULL;
2723 #endif /* HAVE_LIBCRYPTO */
2724  delete_isupport("INVEX");
2725  delete_isupport("EXCEPTS");
2726 }
2727
2728 /* flush_deleted_I_P()
2729 *
2730 * inputs       - none
2731 * output       - none
2732 * side effects - This function removes I/P conf items
2733 */
2734 static void
2735 flush_deleted_I_P(void)
2736 {
2737  dlink_node *ptr;
2738  dlink_node *next_ptr;
2739  struct ConfItem *conf;
2740  struct AccessItem *aconf;
2741  dlink_list * free_items [] = {
2742    &server_items, &oconf_items, NULL
2743  };
2744  dlink_list ** iterator = free_items; /* C is dumb */
2745
2746  /* flush out deleted I and P lines
2747   * although still in use.
2748   */
2749  for (; *iterator != NULL; iterator++)
2750  {
2751    DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2752    {
2753      conf = ptr->data;
2754      aconf = (struct AccessItem *)map_to_conf(conf);
2755
2756      if (IsConfIllegal(aconf))
2757      {
2758        dlinkDelete(ptr, *iterator);
2759
2760        if (aconf->clients == 0)
2761          delete_conf_item(conf);
2762      }
2763    }
2764  }
2765 }
2766
2767 /* get_conf_name()
2768 *
2769 * inputs       - type of conf file to return name of file for
2770 * output       - pointer to filename for type of conf
2771 * side effects - none
2772 */
2773 const char *
2774 get_conf_name(ConfType type)
2775 {
2776  switch (type)
2777  {
2778    case CONF_TYPE:
2779      return ConfigFileEntry.configfile;
2780      break;
2781    case KLINE_TYPE:
2782      return ConfigFileEntry.klinefile;
2783      break;
2784    case RKLINE_TYPE:
2785      return ConfigFileEntry.rklinefile;
2786      break;
2787    case DLINE_TYPE:
2788      return ConfigFileEntry.dlinefile;
2789      break;
2790    case XLINE_TYPE:
2791      return ConfigFileEntry.xlinefile;
2792      break;
2793    case RXLINE_TYPE:
2794      return ConfigFileEntry.rxlinefile;
2795      break;
2796    case CRESV_TYPE:
2797      return ConfigFileEntry.cresvfile;
2798      break;
2799    case NRESV_TYPE:
2800      return ConfigFileEntry.nresvfile;
2801      break;
2802    case GLINE_TYPE:
2803      return ConfigFileEntry.glinefile;
2804      break;
2805
2806    default:
2807      return NULL;  /* This should NEVER HAPPEN since we call this function
2808                       only with the above values, this will cause us to core
2809                       at some point if this happens so we know where it was */
2810  }
2811 }
2812
2813 #define BAD_PING (-1)
2814
2815 /* get_conf_ping()
2816 *
2817 * inputs       - pointer to struct AccessItem
2818 *              - pointer to a variable that receives ping warning time
2819 * output       - ping frequency
2820 * side effects - NONE
2821 */
2822 static int
2823 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2824 {
2825  struct ClassItem *aclass;
2826  struct AccessItem *aconf;
2827
2828  if (conf != NULL)
2829  {
2830    aconf = (struct AccessItem *)map_to_conf(conf);
2831    if (aconf->class_ptr != NULL)
2832    {
2833      aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2834      *pingwarn = PingWarning(aclass);
2835      return PingFreq(aclass);
2836    }
2837  }
2838
2839  return BAD_PING;
2840 }
2841
2842 /* get_client_class()
2843 *
2844 * inputs       - pointer to client struct
2845 * output       - pointer to name of class
2846 * side effects - NONE
2847 */
2848 const char *
2849 get_client_class(struct Client *target_p)
2850 {
2851  dlink_node *ptr;
2852  struct ConfItem *conf;
2853  struct AccessItem *aconf;
2854
2855  if (target_p != NULL && !IsMe(target_p) &&
2856      target_p->localClient->confs.head != NULL)
2857  {
2858    DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2859    {
2860      conf = ptr->data;
2861
2862      if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2863          conf->type == OPER_TYPE)
2864      {
2865        aconf = (struct AccessItem *) map_to_conf(conf);
2866        if (aconf->class_ptr != NULL)
2867          return aconf->class_ptr->name;
2868      }
2869    }
2870  }
2871
2872  return "default";
2873 }
2874
2875 /* get_client_ping()
2876 *
2877 * inputs       - pointer to client struct
2878 *              - pointer to a variable that receives ping warning time
2879 * output       - ping frequency
2880 * side effects - NONE
2881 */
2882 int
2883 get_client_ping(struct Client *target_p, int *pingwarn)
2884 {
2885  int ping;
2886  struct ConfItem *conf;
2887  dlink_node *nlink;
2888
2889  if (target_p->localClient->confs.head != NULL)
2890    DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2891    {
2892      conf = nlink->data;
2893
2894      if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2895          (conf->type == OPER_TYPE))
2896      {
2897        ping = get_conf_ping(conf, pingwarn);
2898        if (ping > 0)
2899          return ping;
2900      }
2901    }
2902
2903  *pingwarn = 0;
2904  return DEFAULT_PINGFREQUENCY;
2905 }
2906
2907 /* find_class()
2908 *
2909 * inputs       - string name of class
2910 * output       - corresponding Class pointer
2911 * side effects - NONE
2912 */
2913 struct ConfItem *
2914 find_class(const char *classname)
2915 {
2916  struct ConfItem *conf;
2917
2918  if ((conf = find_exact_name_conf(CLASS_TYPE, classname, NULL, NULL)) != NULL)
2919    return conf;
2920
2921  return class_default;
2922 }
2923
2924 /* check_class()
2925 *
2926 * inputs       - NONE
2927 * output       - NONE
2928 * side effects -
2929 */
2930 void
2931 check_class(void)
2932 {
2933  dlink_node *ptr = NULL, *next_ptr = NULL;
2934
2935  DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2936  {
2937    struct ClassItem *aclass = map_to_conf(ptr->data);
2938
2939    if (!aclass->active && !CurrUserCount(aclass))
2940    {
2941      destroy_cidr_class(aclass);
2942      delete_conf_item(ptr->data);
2943    }
2944  }
2945 }
2946
2947 /* init_class()
2948 *
2949 * inputs       - NONE
2950 * output       - NONE
2951 * side effects -
2952 */
2953 void
2954 init_class(void)
2955 {
2956  struct ClassItem *aclass;
2957
2958  class_default = make_conf_item(CLASS_TYPE);
2959
2960  aclass = map_to_conf(class_default);
2961  aclass->active = 1;
2962  DupString(class_default->name, "default");
2963  ConFreq(aclass)  = DEFAULT_CONNECTFREQUENCY;
2964  PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
2965  MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
2966  MaxSendq(aclass) = DEFAULT_SENDQ;
2967
2968  client_check_cb = register_callback("check_client", check_client);
2969 }
2970
2971 /* get_sendq()
2972 *
2973 * inputs       - pointer to client
2974 * output       - sendq for this client as found from its class
2975 * side effects - NONE
2976 */
2977 unsigned int
2978 get_sendq(struct Client *client_p)
2979 {
2980  unsigned int sendq = DEFAULT_SENDQ;
2981  dlink_node *ptr;
2982  struct ConfItem *conf;
2983  struct ConfItem *class_conf;
2984  struct ClassItem *aclass;
2985  struct AccessItem *aconf;
2986
2987  if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2988  {
2989    DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2990    {
2991      conf = ptr->data;
2992      if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2993          || (conf->type == CLIENT_TYPE))
2994      {
2995        aconf = (struct AccessItem *)map_to_conf(conf);
2996        if ((class_conf = aconf->class_ptr) == NULL)
2997          continue;
2998        aclass = (struct ClassItem *)map_to_conf(class_conf);
2999        sendq = MaxSendq(aclass);
3000        return sendq;
3001      }
3002    }
3003  }
3004  /* XXX return a default?
3005   * if here, then there wasn't an attached conf with a sendq
3006   * that is very bad -Dianora
3007   */
3008  return DEFAULT_SENDQ;
1606   }
1607  
1608   /* conf_add_class_to_conf()
1609   *
1610   * inputs       - pointer to config item
1611   * output       - NONE
1612 < * side effects - Add a class pointer to a conf
1612 > * side effects - Add a class pointer to a conf
1613   */
1614   void
1615 < conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
1615 > conf_add_class_to_conf(struct MaskItem *conf, const char *class_name)
1616   {
1617 <  struct AccessItem *aconf = map_to_conf(conf);
3021 <  struct ClassItem *class = NULL;
3022 <
3023 <  if (class_name == NULL)
1617 >  if (class_name == NULL)
1618    {
1619 <    aconf->class_ptr = class_default;
1619 >    conf->class = class_default;
1620  
1621 <    if (conf->type == CLIENT_TYPE)
1622 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1623 <                           "Warning *** Defaulting to default class for %s@%s",
1624 <                           aconf->user, aconf->host);
1621 >    if (conf->type == CONF_CLIENT)
1622 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1623 >                           "Warning *** Defaulting to default class for %s@%s",
1624 >                           conf->user, conf->host);
1625      else
1626 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1627 <                           "Warning *** Defaulting to default class for %s",
1628 <                           conf->name);
1626 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1627 >                           "Warning *** Defaulting to default class for %s",
1628 >                           conf->name);
1629    }
1630    else
1631 <    aconf->class_ptr = find_class(class_name);
3038 <
3039 <  if (aconf->class_ptr)
3040 <    class = map_to_conf(aconf->class_ptr);
1631 >    conf->class = class_find(class_name, 1);
1632  
1633 <  if (aconf->class_ptr == NULL || !class->active)
1633 >  if (conf->class == NULL)
1634    {
1635 <    if (conf->type == CLIENT_TYPE)
1636 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1637 <                           "Warning *** Defaulting to default class for %s@%s",
1638 <                           aconf->user, aconf->host);
1635 >    if (conf->type == CONF_CLIENT)
1636 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1637 >                           "Warning *** Defaulting to default class for %s@%s",
1638 >                           conf->user, conf->host);
1639      else
1640 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1641 <                           "Warning *** Defaulting to default class for %s",
1642 <                           conf->name);
1643 <    aconf->class_ptr = class_default;
3053 <  }
3054 < }
3055 <
3056 < /* conf_add_server()
3057 < *
3058 < * inputs       - pointer to config item
3059 < *              - pointer to link count already on this conf
3060 < * output       - NONE
3061 < * side effects - Add a connect block
3062 < */
3063 < int
3064 < conf_add_server(struct ConfItem *conf, const char *class_name)
3065 < {
3066 <  struct AccessItem *aconf;
3067 <  struct split_nuh_item nuh;
3068 <  char conf_user[USERLEN + 1];
3069 <  char conf_host[HOSTLEN + 1];
3070 <
3071 <  aconf = map_to_conf(conf);
3072 <
3073 <  conf_add_class_to_conf(conf, class_name);
3074 <
3075 <  if (!aconf->host || !conf->name)
3076 <  {
3077 <    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
3078 <    ilog(L_WARN, "Bad connect block");
3079 <    return -1;
1640 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1641 >                           "Warning *** Defaulting to default class for %s",
1642 >                           conf->name);
1643 >    conf->class = class_default;
1644    }
3081
3082  if (EmptyString(aconf->passwd) && !IsConfCryptLink(aconf))
3083  {
3084    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
3085                         conf->name);
3086    ilog(L_WARN, "Bad connect block, host %s", conf->name);
3087    return -1;
3088  }
3089
3090  nuh.nuhmask  = aconf->host;
3091  nuh.nickptr  = NULL;
3092  nuh.userptr  = conf_user;
3093  nuh.hostptr  = conf_host;
3094
3095  nuh.nicksize = 0;
3096  nuh.usersize = sizeof(conf_user);
3097  nuh.hostsize = sizeof(conf_host);
3098
3099  split_nuh(&nuh);
3100
3101  MyFree(aconf->host);
3102  aconf->host = NULL;
3103
3104  DupString(aconf->user, conf_user); /* somehow username checking for servers
3105                                 got lost in H6/7, will have to be re-added */
3106  DupString(aconf->host, conf_host);
3107
3108  lookup_confhost(conf);
3109
3110  return 0;
1645   }
1646  
1647   /* yyerror()
# Line 3125 | Line 1659 | yyerror(const char *msg)
1659      return;
1660  
1661    strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1662 <  sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
1662 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1663 >                       "\"%s\", line %u: %s: %s",
1664                         conffilebuf, lineno + 1, msg, newlinebuf);
1665 <  ilog(L_WARN, "\"%s\", line %u: %s: %s",
1665 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1666         conffilebuf, lineno + 1, msg, newlinebuf);
1667   }
1668  
1669 < int
1670 < conf_fbgets(char *lbuf, unsigned int max_size, FBFILE *fb)
1669 > void
1670 > conf_error_report(const char *msg)
1671   {
1672 <  if (fbgets(lbuf, max_size, fb) == NULL)
3138 <    return 0;
3139 <
3140 <  return strlen(lbuf);
3141 < }
1672 >  char newlinebuf[IRCD_BUFSIZE];
1673  
1674 < int
1675 < conf_yy_fatal_error(const char *msg)
1676 < {
1677 <  return 0;
1674 >  strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1675 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1676 >                       "\"%s\", line %u: %s: %s",
1677 >                       conffilebuf, lineno + 1, msg, newlinebuf);
1678 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1679 >       conffilebuf, lineno + 1, msg, newlinebuf);
1680   }
1681  
1682   /*
1683   * valid_tkline()
1684 < *
1684 > *
1685   * inputs       - pointer to ascii string to check
1686   *              - whether the specified time is in seconds or minutes
1687   * output       - -1 not enough parameters
# Line 3157 | Line 1690 | conf_yy_fatal_error(const char *msg)
1690   * Originally written by Dianora (Diane, db@db.net)
1691   */
1692   time_t
1693 < valid_tkline(const char *p, int minutes)
1693 > valid_tkline(const char *data, const int minutes)
1694   {
1695 +  const unsigned char *p = (const unsigned char *)data;
1696 +  unsigned char tmpch = '\0';
1697    time_t result = 0;
1698  
1699 <  for (; *p; ++p)
1699 >  while ((tmpch = *p++))
1700    {
1701 <    if (!IsDigit(*p))
1701 >    if (!IsDigit(tmpch))
1702        return 0;
1703  
1704      result *= 10;
1705 <    result += ((*p) & 0xF);
1705 >    result += (tmpch & 0xF);
1706    }
1707  
1708    /*
1709 <   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1709 >   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1710     * i.e. they specifically use 0, I am going to return 1 instead
1711     * as a return value of non-zero is used to flag it as a temporary kline
1712     */
1713    if (result == 0)
1714      result = 1;
1715  
1716 <  /*
1716 >  /*
1717     * If the incoming time is in seconds convert it to minutes for the purpose
1718     * of this calculation
1719     */
1720    if (!minutes)
1721 <    result = result / (time_t)60;
1721 >    result = result / 60;
1722  
1723    if (result > MAX_TDKLINE_TIME)
1724      result = MAX_TDKLINE_TIME;
1725  
1726 <  result = result * (time_t)60;  /* turn it into seconds */
1726 >  result = result * 60;  /* turn it into seconds */
1727  
1728    return result;
1729   }
1730  
1731 + /* valid_wild_card_simple()
1732 + *
1733 + * inputs       - data to check for sufficient non-wildcard characters
1734 + * outputs      - 1 if valid, else 0
1735 + * side effects - none
1736 + */
1737 + int
1738 + valid_wild_card_simple(const char *data)
1739 + {
1740 +  const unsigned char *p = (const unsigned char *)data;
1741 +  unsigned char tmpch = '\0';
1742 +  int nonwild = 0;
1743 +
1744 +  while ((tmpch = *p++))
1745 +  {
1746 +    if (tmpch == '\\')
1747 +    {
1748 +      ++p;
1749 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1750 +        return 1;
1751 +    }
1752 +    else if (!IsMWildChar(tmpch))
1753 +    {
1754 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1755 +        return 1;
1756 +    }
1757 +  }
1758 +
1759 +  return 0;
1760 + }
1761 +
1762   /* valid_wild_card()
1763   *
1764   * input        - pointer to client
# Line 3204 | Line 1770 | valid_tkline(const char *p, int minutes)
1770   int
1771   valid_wild_card(struct Client *source_p, int warn, int count, ...)
1772   {
3207  char *p;
1773    char tmpch;
1774    int nonwild = 0;
1775    va_list args;
# Line 3225 | Line 1790 | valid_wild_card(struct Client *source_p,
1790  
1791    while (count--)
1792    {
1793 <    p = va_arg(args, char *);
1793 >    const char *p = va_arg(args, const char *);
1794      if (p == NULL)
1795        continue;
1796  
# Line 3238 | Line 1803 | valid_wild_card(struct Client *source_p,
1803           * break - no point in searching further.
1804           */
1805          if (++nonwild >= ConfigFileEntry.min_nonwildcard)
1806 +        {
1807 +          va_end(args);
1808            return 1;
1809 +        }
1810        }
1811      }
1812    }
1813  
1814    if (warn)
1815 <    sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
1816 <               me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
1815 >    sendto_one_notice(source_p, &me,
1816 >                      ":Please include at least %d non-wildcard characters with the mask",
1817 >                      ConfigFileEntry.min_nonwildcard);
1818 >  va_end(args);
1819    return 0;
1820   }
1821  
# Line 3259 | Line 1829 | valid_wild_card(struct Client *source_p,
1829   *              - parse_flags bit map of things to test
1830   *              - pointer to user or string to parse into
1831   *              - pointer to host or NULL to parse into if non NULL
1832 < *              - pointer to optional tkline time or NULL
1832 > *              - pointer to optional tkline time or NULL
1833   *              - pointer to target_server to parse into if non NULL
1834   *              - pointer to reason to parse into
1835   *
# Line 3281 | Line 1851 | valid_wild_card(struct Client *source_p,
1851   */
1852   int
1853   parse_aline(const char *cmd, struct Client *source_p,
1854 <            int parc, char **parv,
1855 <            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1856 <            char **target_server, char **reason)
1854 >            int parc, char **parv,
1855 >            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1856 >            char **target_server, char **reason)
1857   {
1858    int found_tkline_time=0;
1859    static char def_reason[] = "No Reason";
# Line 3304 | Line 1874 | parse_aline(const char *cmd, struct Clie
1874        *tkline_time = found_tkline_time;
1875      else
1876      {
1877 <      sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3308 <                 me.name, source_p->name, cmd);
1877 >      sendto_one_notice(source_p, &me, ":temp_line not supported by %s", cmd);
1878        return -1;
1879      }
1880    }
1881  
1882    if (parc == 0)
1883    {
1884 <    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3316 <               me.name, source_p->name, cmd);
1884 >    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1885      return -1;
1886    }
1887  
# Line 3327 | Line 1895 | parse_aline(const char *cmd, struct Clie
1895      *up_p = user;
1896      *h_p = host;
1897    }
1898 <
1898 >
1899    parc--;
1900    parv++;
1901  
# Line 3340 | Line 1908 | parse_aline(const char *cmd, struct Clie
1908  
1909        if (target_server == NULL)
1910        {
1911 <        sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
1912 <                   me.name, source_p->name, cmd);
3345 <        return -1;
1911 >        sendto_one_notice(source_p, &me, ":ON server not supported by %s", cmd);
1912 >        return -1;
1913        }
1914  
1915        if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
1916        {
1917 <        sendto_one(source_p, form_str(ERR_NOPRIVS),
3351 <                   me.name, source_p->name, "remoteban");
1917 >        sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "remoteban");
1918          return -1;
1919        }
1920  
1921        if (parc == 0 || EmptyString(*parv))
1922        {
1923 <        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1924 <                   me.name, source_p->name, cmd);
3359 <        return -1;
1923 >        sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1924 >        return -1;
1925        }
1926  
1927        *target_server = *parv;
# Line 3369 | Line 1934 | parse_aline(const char *cmd, struct Clie
1934         * caller probably NULL'd it first, but no harm to do it again -db
1935         */
1936        if (target_server != NULL)
1937 <        *target_server = NULL;
1937 >        *target_server = NULL;
1938      }
1939    }
1940  
# Line 3377 | Line 1942 | parse_aline(const char *cmd, struct Clie
1942    {
1943      if (strchr(user, '!') != NULL)
1944      {
1945 <      sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3381 <                 me.name, source_p->name);
1945 >      sendto_one_notice(source_p, &me, ":Invalid character '!' in kline");
1946        return -1;
1947      }
1948  
# Line 3395 | Line 1959 | parse_aline(const char *cmd, struct Clie
1959      {
1960        *reason = *parv;
1961        if (!valid_comment(source_p, *reason, 1))
1962 <        return -1;
1962 >        return -1;
1963      }
1964      else
1965        *reason = def_reason;
# Line 3434 | Line 1998 | find_user_host(struct Client *source_p,
1998      {
1999        *(hostp++) = '\0';                       /* short and squat */
2000        if (*user_host_or_nick)
2001 <        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
2001 >        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
2002        else
2003 <        strcpy(luser, "*");
2003 >        strcpy(luser, "*");
2004 >
2005        if (*hostp)
2006 <        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
2006 >        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
2007        else
2008 <        strcpy(lhost, "*");
2008 >        strcpy(lhost, "*");
2009      }
2010      else
2011      {
2012        luser[0] = '*';             /* no @ found, assume its *@somehost */
2013 <      luser[1] = '\0';    
2013 >      luser[1] = '\0';
2014        strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
2015      }
2016 <    
2016 >
2017      return 1;
2018    }
2019 <  else if (!(flags & NOUSERLOOKUP))
2019 >  else
2020    {
2021      /* Try to find user@host mask from nick */
2022      /* Okay to use source_p as the first param, because source_p == client_p */
2023 <    if ((target_p =
2024 <        find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
2023 >    if ((target_p =
2024 >        find_chasing(source_p, user_host_or_nick)) == NULL)
2025        return 0;
2026  
2027      if (IsExemptKline(target_p))
2028      {
2029        if (!IsServer(source_p))
2030 <        sendto_one(source_p,
3466 <                   ":%s NOTICE %s :%s is E-lined",
3467 <                   me.name, source_p->name, target_p->name);
2030 >        sendto_one_notice(source_p, &me, ":%s is E-lined", target_p->name);
2031        return 0;
2032      }
2033  
# Line 3499 | Line 2062 | find_user_host(struct Client *source_p,
2062   int
2063   valid_comment(struct Client *source_p, char *comment, int warn)
2064   {
3502  if (strchr(comment, '"'))
3503  {
3504    if (warn)
3505      sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3506                 me.name, source_p->name);
3507    return 0;
3508  }
3509
2065    if (strlen(comment) > REASONLEN)
2066      comment[REASONLEN-1] = '\0';
2067  
# Line 3521 | Line 2076 | valid_comment(struct Client *source_p, c
2076   * side effects - none
2077   */
2078   int
2079 < match_conf_password(const char *password, const struct AccessItem *aconf)
2079 > match_conf_password(const char *password, const struct MaskItem *conf)
2080   {
2081    const char *encr = NULL;
2082  
2083 <  if (password == NULL || aconf->passwd == NULL)
2083 >  if (EmptyString(password) || EmptyString(conf->passwd))
2084      return 0;
2085  
2086 <  if (aconf->flags & CONF_FLAGS_ENCRYPTED)
2087 <  {
3533 <    /* use first two chars of the password they send in as salt */
3534 <    /* If the password in the conf is MD5, and ircd is linked
3535 <     * to scrypt on FreeBSD, or the standard crypt library on
3536 <     * glibc Linux, then this code will work fine on generating
3537 <     * the proper encrypted hash for comparison.
3538 <     */
3539 <    if (*aconf->passwd)
3540 <      encr = crypt(password, aconf->passwd);
3541 <    else
3542 <      encr = "";
3543 <  }
2086 >  if (conf->flags & CONF_FLAGS_ENCRYPTED)
2087 >    encr = crypt(password, conf->passwd);
2088    else
2089      encr = password;
2090  
2091 <  return !strcmp(encr, aconf->passwd);
2091 >  return !strcmp(encr, conf->passwd);
2092   }
2093  
2094   /*
# Line 3553 | Line 2097 | match_conf_password(const char *password
2097   * inputs       - client sending the cluster
2098   *              - command name "KLINE" "XLINE" etc.
2099   *              - capab -- CAP_KLN etc. from s_serv.h
2100 < *              - cluster type -- CLUSTER_KLINE etc. from s_conf.h
2100 > *              - cluster type -- CLUSTER_KLINE etc. from conf.h
2101   *              - pattern and args to send along
2102   * output       - none
2103   * side effects - Take source_p send the pattern with args given
# Line 3573 | Line 2117 | cluster_a_line(struct Client *source_p,
2117  
2118    DLINK_FOREACH(ptr, cluster_items.head)
2119    {
2120 <    const struct ConfItem *conf = ptr->data;
2120 >    const struct MaskItem *conf = ptr->data;
2121  
2122      if (conf->flags & cluster_type)
2123        sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
2124 <                         "%s %s %s", command, conf->name, buffer);
2124 >                         "%s %s %s", command, conf->name, buffer);
2125    }
2126   }
2127  
# Line 3628 | Line 2172 | split_nuh(struct split_nuh_item *const i
2172      if (iptr->nickptr && *iptr->nuhmask != '\0')
2173        strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
2174  
2175 <    if ((q = strchr(++p, '@'))) {
2175 >    if ((q = strchr(++p, '@')))
2176 >    {
2177        *q++ = '\0';
2178  
2179        if (*p != '\0')
# Line 3667 | Line 2212 | split_nuh(struct split_nuh_item *const i
2212      }
2213    }
2214   }
3670
3671 /*
3672 * flags_to_ascii
3673 *
3674 * inputs       - flags is a bitmask
3675 *              - pointer to table of ascii letters corresponding
3676 *                to each bit
3677 *              - flag 1 for convert ToLower if bit missing
3678 *                0 if ignore.
3679 * output       - none
3680 * side effects - string pointed to by p has bitmap chars written to it
3681 */
3682 static void
3683 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3684               int lowerit)
3685 {
3686  unsigned int mask = 1;
3687  int i = 0;
3688
3689  for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3690  {
3691    if (flags & mask)
3692      *p++ = bit_table[i];
3693    else if (lowerit)
3694      *p++ = ToLower(bit_table[i]);
3695  }
3696  *p = '\0';
3697 }
3698
3699 /*
3700 * cidr_limit_reached
3701 *
3702 * inputs       - int flag allowing over_rule of limits
3703 *              - pointer to the ip to be added
3704 *              - pointer to the class
3705 * output       - non zero if limit reached
3706 *                0 if limit not reached
3707 * side effects -
3708 */
3709 static int
3710 cidr_limit_reached(int over_rule,
3711                   struct irc_ssaddr *ip, struct ClassItem *aclass)
3712 {
3713  dlink_node *ptr = NULL;
3714  struct CidrItem *cidr;
3715
3716  if (NumberPerCidr(aclass) <= 0)
3717    return 0;
3718
3719  if (ip->ss.ss_family == AF_INET)
3720  {
3721    if (CidrBitlenIPV4(aclass) <= 0)
3722      return 0;
3723
3724    DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3725    {
3726      cidr = ptr->data;
3727      if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3728      {
3729        if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3730          return -1;
3731        cidr->number_on_this_cidr++;
3732        return 0;
3733      }
3734    }
3735    cidr = MyMalloc(sizeof(struct CidrItem));
3736    cidr->number_on_this_cidr = 1;
3737    cidr->mask = *ip;
3738    mask_addr(&cidr->mask, CidrBitlenIPV4(aclass));
3739    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3740  }
3741 #ifdef IPV6
3742  else if (CidrBitlenIPV6(aclass) > 0)
3743  {
3744    DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3745    {
3746      cidr = ptr->data;
3747      if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3748      {
3749        if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3750          return -1;
3751        cidr->number_on_this_cidr++;
3752        return 0;
3753      }
3754    }
3755    cidr = MyMalloc(sizeof(struct CidrItem));
3756    cidr->number_on_this_cidr = 1;
3757    cidr->mask = *ip;
3758    mask_addr(&cidr->mask, CidrBitlenIPV6(aclass));
3759    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3760  }
3761 #endif
3762  return 0;
3763 }
3764
3765 /*
3766 * remove_from_cidr_check
3767 *
3768 * inputs       - pointer to the ip to be removed
3769 *              - pointer to the class
3770 * output       - NONE
3771 * side effects -
3772 */
3773 static void
3774 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3775 {
3776  dlink_node *ptr = NULL;
3777  dlink_node *next_ptr = NULL;
3778  struct CidrItem *cidr;
3779
3780  if (NumberPerCidr(aclass) == 0)
3781    return;
3782
3783  if (ip->ss.ss_family == AF_INET)
3784  {
3785    if (CidrBitlenIPV4(aclass) <= 0)
3786      return;
3787
3788    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3789    {
3790      cidr = ptr->data;
3791      if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3792      {
3793        cidr->number_on_this_cidr--;
3794        if (cidr->number_on_this_cidr == 0)
3795        {
3796          dlinkDelete(ptr, &aclass->list_ipv4);
3797          MyFree(cidr);
3798          return;
3799        }
3800      }
3801    }
3802  }
3803 #ifdef IPV6
3804  else if (CidrBitlenIPV6(aclass) > 0)
3805  {
3806    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3807    {
3808      cidr = ptr->data;
3809      if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3810      {
3811        cidr->number_on_this_cidr--;
3812        if (cidr->number_on_this_cidr == 0)
3813        {
3814          dlinkDelete(ptr, &aclass->list_ipv6);
3815          MyFree(cidr);
3816          return;
3817        }
3818      }
3819    }
3820  }
3821 #endif
3822 }
3823
3824 static void
3825 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3826                  dlink_list *old_list, dlink_list *new_list, int changed)
3827 {
3828  dlink_node *ptr;
3829  struct Client *client_p;
3830  struct ConfItem *conf;
3831  struct AccessItem *aconf;
3832
3833  if (!changed)
3834  {
3835    *new_list = *old_list;
3836    old_list->head = old_list->tail = NULL;
3837    old_list->length = 0;
3838    return;
3839  }
3840
3841  DLINK_FOREACH(ptr, local_client_list.head)
3842  {
3843    client_p = ptr->data;
3844    if (client_p->localClient->aftype != aftype)
3845      continue;
3846    if (dlink_list_length(&client_p->localClient->confs) == 0)
3847      continue;
3848
3849    conf = client_p->localClient->confs.tail->data;
3850    if (conf->type == CLIENT_TYPE)
3851    {
3852      aconf = map_to_conf(conf);
3853      if (aconf->class_ptr == oldcl)
3854        cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3855    }
3856  }
3857 }
3858
3859 /*
3860 * rebuild_cidr_class
3861 *
3862 * inputs       - pointer to old conf
3863 *              - pointer to new_class
3864 * output       - none
3865 * side effects - rebuilds the class link list of cidr blocks
3866 */
3867 void
3868 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3869 {
3870  struct ClassItem *old_class = map_to_conf(conf);
3871
3872  if (NumberPerCidr(old_class) > 0 && NumberPerCidr(new_class) > 0)
3873  {
3874    if (CidrBitlenIPV4(old_class) > 0 && CidrBitlenIPV4(new_class) > 0)
3875      rebuild_cidr_list(AF_INET, conf, new_class,
3876                        &old_class->list_ipv4, &new_class->list_ipv4,
3877                        CidrBitlenIPV4(old_class) != CidrBitlenIPV4(new_class));
3878
3879 #ifdef IPV6
3880    if (CidrBitlenIPV6(old_class) > 0 && CidrBitlenIPV6(new_class) > 0)
3881      rebuild_cidr_list(AF_INET6, conf, new_class,
3882                        &old_class->list_ipv6, &new_class->list_ipv6,
3883                        CidrBitlenIPV6(old_class) != CidrBitlenIPV6(new_class));
3884 #endif
3885  }
3886
3887  destroy_cidr_class(old_class);
3888 }
3889
3890 /*
3891 * destroy_cidr_list
3892 *
3893 * inputs       - pointer to class dlink list of cidr blocks
3894 * output       - none
3895 * side effects - completely destroys the class link list of cidr blocks
3896 */
3897 static void
3898 destroy_cidr_list(dlink_list *list)
3899 {
3900  dlink_node *ptr = NULL, *next_ptr = NULL;
3901
3902  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3903  {
3904    dlinkDelete(ptr, list);
3905    MyFree(ptr->data);
3906  }
3907 }
3908
3909 /*
3910 * destroy_cidr_class
3911 *
3912 * inputs       - pointer to class
3913 * output       - none
3914 * side effects - completely destroys the class link list of cidr blocks
3915 */
3916 static void
3917 destroy_cidr_class(struct ClassItem *aclass)
3918 {
3919  destroy_cidr_list(&aclass->list_ipv4);
3920  destroy_cidr_list(&aclass->list_ipv6);
3921 }

Diff Legend

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