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/trunk/src/conf.c (file contents):
Revision 1618 by michael, Tue Oct 30 21:04:38 2012 UTC vs.
Revision 2313 by michael, Fri Jun 21 11:40:50 2013 UTC

# Line 25 | Line 25
25   #include "stdinc.h"
26   #include "list.h"
27   #include "ircd_defs.h"
28 #include "balloc.h"
28   #include "conf.h"
29   #include "s_serv.h"
30   #include "resv.h"
# Line 45 | Line 44
44   #include "send.h"
45   #include "s_gline.h"
46   #include "memory.h"
47 + #include "mempool.h"
48   #include "irc_res.h"
49   #include "userhost.h"
50   #include "s_user.h"
51   #include "channel_mode.h"
52   #include "parse.h"
53   #include "s_misc.h"
54 + #include "conf_db.h"
55 + #include "conf_class.h"
56 + #include "motd.h"
57  
55 struct Callback *client_check_cb = NULL;
58   struct config_server_hide ConfigServerHide;
59  
60   /* general conf items link list root, other than k lines etc. */
# Line 62 | Line 64 | dlink_list cluster_items = { NULL, NULL,
64   dlink_list oconf_items   = { NULL, NULL, 0 };
65   dlink_list uconf_items   = { NULL, NULL, 0 };
66   dlink_list xconf_items   = { NULL, NULL, 0 };
65 dlink_list rxconf_items  = { NULL, NULL, 0 };
66 dlink_list rkconf_items  = { NULL, NULL, 0 };
67   dlink_list nresv_items   = { NULL, NULL, 0 };
68 < dlink_list class_items   = { NULL, NULL, 0 };
69 <
70 < dlink_list temporary_xlines  = { NULL, NULL, 0 };
71 < dlink_list temporary_resv = { NULL, NULL, 0 };
68 > dlink_list cresv_items = { NULL, NULL, 0 };
69  
70   extern unsigned int lineno;
71   extern char linebuf[];
# Line 80 | Line 77 | struct conf_parser_context conf_parser_c
77   /* internally defined functions */
78   static void read_conf(FILE *);
79   static void clear_out_old_conf(void);
83 static void flush_deleted_I_P(void);
80   static void expire_tklines(dlink_list *);
81   static void garbage_collect_ip_entries(void);
82   static int hash_ip(struct irc_ssaddr *);
83 < static int verify_access(struct Client *, const char *);
84 < static int attach_iline(struct Client *, struct ConfItem *);
83 > static int verify_access(struct Client *);
84 > static int attach_iline(struct Client *, struct MaskItem *);
85   static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
86 < static void parse_conf_file(int, int);
91 < static dlink_list *map_to_list(ConfType);
92 < static struct AccessItem *find_regexp_kline(const char *[]);
86 > static dlink_list *map_to_list(enum maskitem_type);
87   static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
88  
95 /*
96 * bit_len
97 */
98 static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
99 static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
100 static void destroy_cidr_class(struct ClassItem *);
101
102 static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
103
104 /* address of default class conf */
105 static struct ConfItem *class_default;
89  
90   /* usually, with hash tables, you use a prime number...
91   * but in this case I am dealing with ip addresses,
# Line 113 | Line 96 | static struct ConfItem *class_default;
96   struct ip_entry
97   {
98    struct irc_ssaddr ip;
99 <  int count;
99 >  unsigned int count;
100    time_t last_attempt;
101    struct ip_entry *next;
102   };
103  
104   static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
105 < static BlockHeap *ip_entry_heap = NULL;
105 > static mp_pool_t *ip_entry_pool = NULL;
106   static int ip_entries_count = 0;
107  
108  
126 void *
127 map_to_conf(struct ConfItem *aconf)
128 {
129  void *conf;
130  conf = (void *)((uintptr_t)aconf +
131                  (uintptr_t)sizeof(struct ConfItem));
132  return(conf);
133 }
134
135 struct ConfItem *
136 unmap_conf_item(void *aconf)
137 {
138  struct ConfItem *conf;
139
140  conf = (struct ConfItem *)((uintptr_t)aconf -
141                             (uintptr_t)sizeof(struct ConfItem));
142  return(conf);
143 }
144
109   /* conf_dns_callback()
110   *
111 < * inputs       - pointer to struct AccessItem
111 > * inputs       - pointer to struct MaskItem
112   *              - pointer to DNSReply reply
113   * output       - none
114   * side effects - called when resolver query finishes
# Line 155 | Line 119 | unmap_conf_item(void *aconf)
119   static void
120   conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
121   {
122 <  struct AccessItem *aconf = vptr;
122 >  struct MaskItem *conf = vptr;
123  
124 <  aconf->dns_pending = 0;
124 >  conf->dns_pending = 0;
125  
126    if (addr != NULL)
127 <    memcpy(&aconf->addr, addr, sizeof(aconf->addr));
127 >    memcpy(&conf->addr, addr, sizeof(conf->addr));
128    else
129 <    aconf->dns_failed = 1;
129 >    conf->dns_failed = 1;
130   }
131  
132   /* conf_dns_lookup()
# Line 172 | Line 136 | conf_dns_callback(void *vptr, const stru
136   * allocate a dns_query and start ns lookup.
137   */
138   static void
139 < conf_dns_lookup(struct AccessItem *aconf)
139 > conf_dns_lookup(struct MaskItem *conf)
140   {
141 <  if (!aconf->dns_pending)
141 >  if (!conf->dns_pending)
142    {
143 <    aconf->dns_pending = 1;
144 <    gethost_byname(conf_dns_callback, aconf, aconf->host);
143 >    conf->dns_pending = 1;
144 >    gethost_byname(conf_dns_callback, conf, conf->host);
145    }
146   }
147  
148 < /* make_conf_item()
149 < *
186 < * inputs       - type of item
187 < * output       - pointer to new conf entry
188 < * side effects - none
189 < */
190 < struct ConfItem *
191 < make_conf_item(ConfType type)
148 > struct MaskItem *
149 > conf_make(enum maskitem_type type)
150   {
151 <  struct ConfItem *conf = NULL;
152 <  struct AccessItem *aconf = NULL;
195 <  struct ClassItem *aclass = NULL;
196 <  int status = 0;
197 <
198 <  switch (type)
199 <  {
200 <  case DLINE_TYPE:
201 <  case EXEMPTDLINE_TYPE:
202 <  case GLINE_TYPE:
203 <  case KLINE_TYPE:
204 <  case CLIENT_TYPE:
205 <  case OPER_TYPE:
206 <  case SERVER_TYPE:
207 <    conf = MyMalloc(sizeof(struct ConfItem) +
208 <                    sizeof(struct AccessItem));
209 <    aconf = map_to_conf(conf);
210 <    aconf->aftype = AF_INET;
211 <
212 <    /* Yes, sigh. switch on type again */
213 <    switch (type)
214 <    {
215 <    case EXEMPTDLINE_TYPE:
216 <      status = CONF_EXEMPTDLINE;
217 <      break;
218 <
219 <    case DLINE_TYPE:
220 <      status = CONF_DLINE;
221 <      break;
151 >  struct MaskItem *conf = MyMalloc(sizeof(*conf));
152 >  dlink_list *list = NULL;
153  
154 <    case KLINE_TYPE:
155 <      status = CONF_KLINE;
156 <      break;
226 <
227 <    case GLINE_TYPE:
228 <      status = CONF_GLINE;
229 <      break;
230 <
231 <    case CLIENT_TYPE:
232 <      status = CONF_CLIENT;
233 <      break;
234 <
235 <    case OPER_TYPE:
236 <      status = CONF_OPERATOR;
237 <      dlinkAdd(conf, &conf->node, &oconf_items);
238 <      break;
239 <
240 <    case SERVER_TYPE:
241 <      status = CONF_SERVER;
242 <      dlinkAdd(conf, &conf->node, &server_items);
243 <      break;
244 <
245 <    default:
246 <      break;
247 <    }
248 <    aconf->status = status;
249 <    break;
250 <
251 <  case ULINE_TYPE:
252 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
253 <                                       sizeof(struct MatchItem));
254 <    dlinkAdd(conf, &conf->node, &uconf_items);
255 <    break;
256 <
257 <  case XLINE_TYPE:
258 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
259 <                                       sizeof(struct MatchItem));
260 <    dlinkAdd(conf, &conf->node, &xconf_items);
261 <    break;
262 < #ifdef HAVE_LIBPCRE
263 <  case RXLINE_TYPE:
264 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
265 <                                       sizeof(struct MatchItem));
266 <    dlinkAdd(conf, &conf->node, &rxconf_items);
267 <    break;
268 <
269 <  case RKLINE_TYPE:
270 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
271 <                                       sizeof(struct AccessItem));
272 <    aconf = map_to_conf(conf);
273 <    aconf->status = CONF_KLINE;
274 <    dlinkAdd(conf, &conf->node, &rkconf_items);
275 <    break;
276 < #endif
277 <  case CLUSTER_TYPE:
278 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
279 <    dlinkAdd(conf, &conf->node, &cluster_items);
280 <    break;
281 <
282 <  case CRESV_TYPE:
283 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
284 <                                       sizeof(struct ResvChannel));
285 <    break;
286 <
287 <  case NRESV_TYPE:
288 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
289 <                                       sizeof(struct MatchItem));
290 <    dlinkAdd(conf, &conf->node, &nresv_items);
291 <    break;
292 <
293 <  case SERVICE_TYPE:
294 <    status = CONF_SERVICE;
295 <    conf = MyMalloc(sizeof(struct ConfItem));
296 <    dlinkAdd(conf, &conf->node, &service_items);
297 <    break;
298 <
299 <  case CLASS_TYPE:
300 <    conf = MyMalloc(sizeof(struct ConfItem) +
301 <                           sizeof(struct ClassItem));
302 <    dlinkAdd(conf, &conf->node, &class_items);
303 <
304 <    aclass = map_to_conf(conf);
305 <    aclass->active = 1;
306 <    aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
307 <    aclass->ping_freq = DEFAULT_PINGFREQUENCY;
308 <    aclass->max_total = MAXIMUM_LINKS_DEFAULT;
309 <    aclass->max_sendq = DEFAULT_SENDQ;
310 <    aclass->max_recvq = DEFAULT_RECVQ;
311 <
312 <    break;
313 <
314 <  default:
315 <    conf = NULL;
316 <    break;
317 <  }
318 <
319 <  /* XXX Yes, this will core if default is hit. I want it to for now - db */
320 <  conf->type = type;
154 >  conf->type   = type;
155 >  conf->active = 1;
156 >  conf->aftype = AF_INET;
157  
158 +  if ((list = map_to_list(type)))
159 +    dlinkAdd(conf, &conf->node, list);
160    return conf;
161   }
162  
163   void
164 < delete_conf_item(struct ConfItem *conf)
164 > conf_free(struct MaskItem *conf)
165   {
166 <  dlink_node *m = NULL, *m_next = NULL;
167 <  struct MatchItem *match_item;
168 <  struct AccessItem *aconf;
169 <  ConfType type = conf->type;
166 >  dlink_node *ptr = NULL, *ptr_next = NULL;
167 >  dlink_list *list = NULL;
168 >
169 >  if (conf->node.next)
170 >    if ((list = map_to_list(conf->type)))
171 >      dlinkDelete(&conf->node, list);
172  
173    MyFree(conf->name);
334  conf->name = NULL;
174  
175 <  switch(type)
176 <  {
177 <  case DLINE_TYPE:
178 <  case EXEMPTDLINE_TYPE:
179 <  case GLINE_TYPE:
180 <  case KLINE_TYPE:
181 <  case CLIENT_TYPE:
182 <  case OPER_TYPE:
183 <  case SERVER_TYPE:
184 <    aconf = map_to_conf(conf);
185 <
186 <    if (aconf->dns_pending)
187 <      delete_resolver_queries(aconf);
188 <    if (aconf->passwd != NULL)
189 <      memset(aconf->passwd, 0, strlen(aconf->passwd));
351 <    if (aconf->spasswd != NULL)
352 <      memset(aconf->spasswd, 0, strlen(aconf->spasswd));
353 <    aconf->class_ptr = NULL;
354 <
355 <    MyFree(aconf->passwd);
356 <    MyFree(aconf->spasswd);
357 <    MyFree(aconf->reason);
358 <    MyFree(aconf->oper_reason);
359 <    MyFree(aconf->user);
360 <    MyFree(aconf->host);
175 >  if (conf->dns_pending)
176 >    delete_resolver_queries(conf);
177 >  if (conf->passwd != NULL)
178 >    memset(conf->passwd, 0, strlen(conf->passwd));
179 >  if (conf->spasswd != NULL)
180 >    memset(conf->spasswd, 0, strlen(conf->spasswd));
181 >
182 >  conf->class = NULL;
183 >
184 >  MyFree(conf->passwd);
185 >  MyFree(conf->spasswd);
186 >  MyFree(conf->reason);
187 >  MyFree(conf->certfp);
188 >  MyFree(conf->user);
189 >  MyFree(conf->host);
190   #ifdef HAVE_LIBCRYPTO
191 <    MyFree(aconf->cipher_list);
363 <
364 <    if (aconf->rsa_public_key)
365 <      RSA_free(aconf->rsa_public_key);
366 <    MyFree(aconf->rsa_public_key_file);
367 < #endif
368 <
369 <    /* Yes, sigh. switch on type again */
370 <    switch(type)
371 <    {
372 <    case EXEMPTDLINE_TYPE:
373 <    case DLINE_TYPE:
374 <    case GLINE_TYPE:
375 <    case KLINE_TYPE:
376 <    case CLIENT_TYPE:
377 <      MyFree(conf);
378 <      break;
191 >  MyFree(conf->cipher_list);
192  
193 <    case OPER_TYPE:
194 <      aconf = map_to_conf(conf);
382 <      if (!IsConfIllegal(aconf))
383 <        dlinkDelete(&conf->node, &oconf_items);
384 <      MyFree(conf);
385 <      break;
386 <
387 <    case SERVER_TYPE:
388 <      aconf = map_to_conf(conf);
389 <
390 <      DLINK_FOREACH_SAFE(m, m_next, aconf->hub_list.head)
391 <      {
392 <        MyFree(m->data);
393 <        free_dlink_node(m);
394 <      }
395 <
396 <      DLINK_FOREACH_SAFE(m, m_next, aconf->leaf_list.head)
397 <      {
398 <        MyFree(m->data);
399 <        free_dlink_node(m);  
400 <      }
401 <
402 <      if (!IsConfIllegal(aconf))
403 <        dlinkDelete(&conf->node, &server_items);
404 <      MyFree(conf);
405 <      break;
406 <
407 <    default:
408 <      break;
409 <    }
410 <    break;
411 <
412 <  case ULINE_TYPE:
413 <    match_item = map_to_conf(conf);
414 <    MyFree(match_item->user);
415 <    MyFree(match_item->host);
416 <    MyFree(match_item->reason);
417 <    MyFree(match_item->oper_reason);
418 <    dlinkDelete(&conf->node, &uconf_items);
419 <    MyFree(conf);
420 <    break;
421 <
422 <  case XLINE_TYPE:
423 <    match_item = map_to_conf(conf);
424 <    MyFree(match_item->user);
425 <    MyFree(match_item->host);
426 <    MyFree(match_item->reason);
427 <    MyFree(match_item->oper_reason);
428 <    dlinkDelete(&conf->node, &xconf_items);
429 <    MyFree(conf);
430 <    break;
431 < #ifdef HAVE_LIBPCRE
432 <  case RKLINE_TYPE:
433 <    aconf = map_to_conf(conf);
434 <    MyFree(aconf->regexuser);
435 <    MyFree(aconf->regexhost);
436 <    MyFree(aconf->user);
437 <    MyFree(aconf->host);
438 <    MyFree(aconf->reason);
439 <    MyFree(aconf->oper_reason);
440 <    dlinkDelete(&conf->node, &rkconf_items);
441 <    MyFree(conf);
442 <    break;
443 <
444 <  case RXLINE_TYPE:
445 <    MyFree(conf->regexpname);
446 <    match_item = map_to_conf(conf);
447 <    MyFree(match_item->user);
448 <    MyFree(match_item->host);
449 <    MyFree(match_item->reason);
450 <    MyFree(match_item->oper_reason);
451 <    dlinkDelete(&conf->node, &rxconf_items);
452 <    MyFree(conf);
453 <    break;
193 >  if (conf->rsa_public_key)
194 >    RSA_free(conf->rsa_public_key);
195   #endif
196 <  case NRESV_TYPE:
197 <    match_item = map_to_conf(conf);
198 <    MyFree(match_item->user);
199 <    MyFree(match_item->host);
459 <    MyFree(match_item->reason);
460 <    MyFree(match_item->oper_reason);
461 <    dlinkDelete(&conf->node, &nresv_items);
462 <
463 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
464 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
465 <        free_dlink_node(m);
466 <
467 <    MyFree(conf);
468 <    break;
469 <
470 <  case CLUSTER_TYPE:
471 <    dlinkDelete(&conf->node, &cluster_items);
472 <    MyFree(conf);
473 <    break;
474 <
475 <  case CRESV_TYPE:
476 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
477 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
478 <        free_dlink_node(m);
479 <
480 <    MyFree(conf);
481 <    break;
482 <
483 <  case CLASS_TYPE:
484 <    dlinkDelete(&conf->node, &class_items);
485 <    MyFree(conf);
486 <    break;
487 <
488 <  case SERVICE_TYPE:
489 <    dlinkDelete(&conf->node, &service_items);
490 <    MyFree(conf);
491 <    break;
492 <
493 <  default:
494 <    break;
196 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->hub_list.head)
197 >  {
198 >    MyFree(ptr->data);
199 >    free_dlink_node(ptr);
200    }
496 }
201  
202 < /* free_access_item()
499 < *
500 < * inputs       - pointer to conf to free
501 < * output       - none
502 < * side effects - crucial password fields are zeroed, conf is freed
503 < */
504 < void
505 < free_access_item(struct AccessItem *aconf)
506 < {
507 <  struct ConfItem *conf;
508 <
509 <  if (aconf == NULL)
510 <    return;
511 <  conf = unmap_conf_item(aconf);
512 <  delete_conf_item(conf);
513 < }
514 <
515 < static const unsigned int shared_bit_table[] =
516 <  { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
517 <
518 < /* report_confitem_types()
519 < *
520 < * inputs       - pointer to client requesting confitem report
521 < *              - ConfType to report
522 < * output       - none
523 < * side effects -
524 < */
525 < void
526 < report_confitem_types(struct Client *source_p, ConfType type)
527 < {
528 <  dlink_node *ptr = NULL, *dptr = NULL;
529 <  struct ConfItem *conf = NULL;
530 <  struct AccessItem *aconf = NULL;
531 <  struct MatchItem *matchitem = NULL;
532 <  struct ClassItem *classitem = NULL;
533 <  char buf[12];
534 <  char *p = NULL;
535 <
536 <  switch (type)
202 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->leaf_list.head)
203    {
204 <  case XLINE_TYPE:
205 <    DLINK_FOREACH(ptr, xconf_items.head)
206 <    {
541 <      conf = ptr->data;
542 <      matchitem = map_to_conf(conf);
543 <
544 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
545 <                 me.name, source_p->name,
546 <                 matchitem->hold ? "x": "X", matchitem->count,
547 <                 conf->name, matchitem->reason);
548 <    }
549 <    break;
550 <
551 < #ifdef HAVE_LIBPCRE
552 <  case RXLINE_TYPE:
553 <    DLINK_FOREACH(ptr, rxconf_items.head)
554 <    {
555 <      conf = ptr->data;
556 <      matchitem = map_to_conf(conf);
557 <
558 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
559 <                 me.name, source_p->name,
560 <                 "XR", matchitem->count,
561 <                 conf->name, matchitem->reason);
562 <    }
563 <    break;
564 <
565 <  case RKLINE_TYPE:
566 <    DLINK_FOREACH(ptr, rkconf_items.head)
567 <    {
568 <      aconf = map_to_conf((conf = ptr->data));
569 <
570 <      sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
571 <                 source_p->name, "KR", aconf->host, aconf->user,
572 <                 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
573 <    }
574 <    break;
575 < #endif
576 <
577 <  case ULINE_TYPE:
578 <    DLINK_FOREACH(ptr, uconf_items.head)
579 <    {
580 <      conf = ptr->data;
581 <      matchitem = map_to_conf(conf);
582 <
583 <      p = buf;
584 <
585 <      /* some of these are redundant for the sake of
586 <       * consistency with cluster{} flags
587 <       */
588 <      *p++ = 'c';
589 <      flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
590 <
591 <      sendto_one(source_p, form_str(RPL_STATSULINE),
592 <                 me.name, source_p->name, conf->name,
593 <                 matchitem->user?matchitem->user: "*",
594 <                 matchitem->host?matchitem->host: "*", buf);
595 <    }
596 <
597 <    DLINK_FOREACH(ptr, cluster_items.head)
598 <    {
599 <      conf = ptr->data;
600 <
601 <      p = buf;
602 <
603 <      *p++ = 'C';
604 <      flags_to_ascii(conf->flags, shared_bit_table, p, 0);
605 <
606 <      sendto_one(source_p, form_str(RPL_STATSULINE),
607 <                 me.name, source_p->name, conf->name,
608 <                 "*", "*", buf);
609 <    }
610 <
611 <    break;
612 <
613 <  case OPER_TYPE:
614 <    DLINK_FOREACH(ptr, oconf_items.head)
615 <    {
616 <      conf = ptr->data;
617 <      aconf = map_to_conf(conf);
618 <
619 <      /* Don't allow non opers to see oper privs */
620 <      if (HasUMode(source_p, UMODE_OPER))
621 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
622 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
623 <                   conf->name, oper_privs_as_string(aconf->port),
624 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
625 <      else
626 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
627 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
628 <                   conf->name, "0",
629 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
630 <    }
631 <    break;
632 <
633 <  case CLASS_TYPE:
634 <    DLINK_FOREACH(ptr, class_items.head)
635 <    {
636 <      conf = ptr->data;
637 <      classitem = map_to_conf(conf);
638 <      sendto_one(source_p, form_str(RPL_STATSYLINE),
639 <                 me.name, source_p->name, 'Y',
640 <                 conf->name, classitem->ping_freq,
641 <                 classitem->con_freq,
642 <                 classitem->max_total, classitem->max_sendq,
643 <                 classitem->max_recvq,
644 <                 classitem->curr_user_count,
645 <                 classitem->number_per_cidr, classitem->cidr_bitlen_ipv4,
646 <                 classitem->number_per_cidr, classitem->cidr_bitlen_ipv6,
647 <                 classitem->active ? "active" : "disabled");
648 <    }
649 <    break;
650 <
651 <  case CONF_TYPE:
652 <  case CLIENT_TYPE:
653 <    break;
654 <
655 <  case SERVICE_TYPE:
656 <    DLINK_FOREACH(ptr, service_items.head)
657 <    {
658 <      conf = ptr->data;
659 <      sendto_one(source_p, form_str(RPL_STATSSERVICE),
660 <                 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
661 <    }
662 <    break;
663 <
664 <  case SERVER_TYPE:
665 <    DLINK_FOREACH(ptr, server_items.head)
666 <    {
667 <      p = buf;
668 <
669 <      conf = ptr->data;
670 <      aconf = map_to_conf(conf);
671 <
672 <      buf[0] = '\0';
673 <
674 <      if (IsConfAllowAutoConn(aconf))
675 <        *p++ = 'A';
676 <      if (IsConfSSL(aconf))
677 <        *p++ = 'S';
678 <      if (buf[0] == '\0')
679 <        *p++ = '*';
680 <
681 <      *p = '\0';
682 <
683 <      /*
684 <       * Allow admins to see actual ips unless hide_server_ips is enabled
685 <       */
686 <      if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
687 <        sendto_one(source_p, form_str(RPL_STATSCLINE),
688 <                   me.name, source_p->name, 'C', aconf->host,
689 <                   buf, conf->name, aconf->port,
690 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
691 <        else
692 <          sendto_one(source_p, form_str(RPL_STATSCLINE),
693 <                     me.name, source_p->name, 'C',
694 <                     "*@127.0.0.1", buf, conf->name, aconf->port,
695 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
696 <    }
697 <    break;
698 <
699 <  case HUB_TYPE:
700 <    DLINK_FOREACH(ptr, server_items.head)
701 <    {
702 <      conf = ptr->data;
703 <      aconf = map_to_conf(conf);
704 <
705 <      DLINK_FOREACH(dptr, aconf->hub_list.head)
706 <        sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
707 <                   source_p->name, 'H', dptr->data, conf->name, 0, "*");
708 <    }
709 <    break;
710 <
711 <  case LEAF_TYPE:
712 <    DLINK_FOREACH(ptr, server_items.head)
713 <    {
714 <      conf = ptr->data;
715 <      aconf = map_to_conf(conf);
204 >    MyFree(ptr->data);
205 >    free_dlink_node(ptr);
206 >  }
207  
208 <      DLINK_FOREACH(dptr, aconf->leaf_list.head)
209 <        sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
210 <                   source_p->name, 'L', dptr->data, conf->name, 0, "*");
720 <    }
721 <    break;
208 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->exempt_list.head)
209 >  {
210 >    struct exempt *exptr = ptr->data;
211  
212 <  case GLINE_TYPE:
213 <  case KLINE_TYPE:
214 <  case DLINE_TYPE:
215 <  case EXEMPTDLINE_TYPE:
727 <  case CRESV_TYPE:
728 <  case NRESV_TYPE:
729 <  case CLUSTER_TYPE:
730 <  default:
731 <    break;
212 >    MyFree(exptr->name);
213 >    MyFree(exptr->user);
214 >    MyFree(exptr->host);
215 >    MyFree(exptr);
216    }
217 +
218 +  MyFree(conf);
219   }
220  
221   /* check_client()
# Line 745 | Line 231 | report_confitem_types(struct Client *sou
231   *                Look for conf lines which have the same
232   *                status as the flags passed.
233   */
234 < static void *
235 < check_client(va_list args)
234 > int
235 > check_client(struct Client *source_p)
236   {
751  struct Client *source_p = va_arg(args, struct Client *);
752  const char *username = va_arg(args, const char *);
237    int i;
238  
239 <  /* I'm already in big trouble if source_p->localClient is NULL -db */
756 <  if ((i = verify_access(source_p, username)))
239 >  if ((i = verify_access(source_p)))
240      ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
241           source_p->name, source_p->sockhost);
242  
# Line 762 | Line 245 | check_client(va_list args)
245      case TOO_MANY:
246        sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
247                             "Too many on IP for %s (%s).",
248 <                           get_client_name(source_p, SHOW_IP),
249 <                           source_p->sockhost);
248 >                           get_client_name(source_p, SHOW_IP),
249 >                           source_p->sockhost);
250        ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
251 <           get_client_name(source_p, SHOW_IP));
251 >           get_client_name(source_p, SHOW_IP));
252        ++ServerStats.is_ref;
253        exit_client(source_p, &me, "No more connections allowed on that IP");
254        break;
# Line 773 | Line 256 | check_client(va_list args)
256      case I_LINE_FULL:
257        sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
258                             "auth{} block is full for %s (%s).",
259 <                           get_client_name(source_p, SHOW_IP),
260 <                           source_p->sockhost);
259 >                           get_client_name(source_p, SHOW_IP),
260 >                           source_p->sockhost);
261        ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
262 <           get_client_name(source_p, SHOW_IP));
262 >           get_client_name(source_p, SHOW_IP));
263        ++ServerStats.is_ref;
264        exit_client(source_p, &me,
265 <                "No more connections allowed in your connection class");
265 >                  "No more connections allowed in your connection class");
266        break;
267  
268      case NOT_AUTHORIZED:
# Line 787 | Line 270 | check_client(va_list args)
270        /* jdc - lists server name & port connections are on */
271        /*       a purely cosmetical change */
272        sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
273 <                           "Unauthorized client connection from %s [%s] on [%s/%u].",
274 <                           get_client_name(source_p, SHOW_IP),
275 <                           source_p->sockhost,
276 <                           source_p->localClient->listener->name,
277 <                           source_p->localClient->listener->port);
273 >                           "Unauthorized client connection from %s [%s] on [%s/%u].",
274 >                           get_client_name(source_p, SHOW_IP),
275 >                           source_p->sockhost,
276 >                           source_p->localClient->listener->name,
277 >                           source_p->localClient->listener->port);
278        ilog(LOG_TYPE_IRCD,
279 <          "Unauthorized client connection from %s on [%s/%u].",
280 <          get_client_name(source_p, SHOW_IP),
281 <          source_p->localClient->listener->name,
282 <          source_p->localClient->listener->port);
279 >           "Unauthorized client connection from %s on [%s/%u].",
280 >           get_client_name(source_p, SHOW_IP),
281 >           source_p->localClient->listener->name,
282 >           source_p->localClient->listener->port);
283  
284        exit_client(source_p, &me, "You are not authorized to use this server");
285        break;
# Line 811 | Line 294 | check_client(va_list args)
294       break;
295    }
296  
297 <  return (i < 0 ? NULL : source_p);
297 >  return (i < 0 ? 0 : 1);
298   }
299  
300   /* verify_access()
301   *
302   * inputs       - pointer to client to verify
820 *              - pointer to proposed username
303   * output       - 0 if success -'ve if not
304   * side effect  - find the first (best) I line to attach.
305   */
306   static int
307 < verify_access(struct Client *client_p, const char *username)
307 > verify_access(struct Client *client_p)
308   {
309 <  struct AccessItem *aconf = NULL, *rkconf = NULL;
828 <  struct ConfItem *conf = NULL;
309 >  struct MaskItem *conf = NULL;
310    char non_ident[USERLEN + 1] = { '~', '\0' };
830  const char *uhi[3];
311  
312    if (IsGotId(client_p))
313    {
314 <    aconf = find_address_conf(client_p->host, client_p->username,
315 <                             &client_p->localClient->ip,
316 <                             client_p->localClient->aftype,
314 >    conf = find_address_conf(client_p->host, client_p->username,
315 >                             &client_p->localClient->ip,
316 >                             client_p->localClient->aftype,
317                               client_p->localClient->passwd);
318    }
319    else
320    {
321 <    strlcpy(non_ident+1, username, sizeof(non_ident)-1);
322 <    aconf = find_address_conf(client_p->host,non_ident,
323 <                             &client_p->localClient->ip,
324 <                             client_p->localClient->aftype,
325 <                             client_p->localClient->passwd);
321 >    strlcpy(non_ident + 1, client_p->username, sizeof(non_ident) - 1);
322 >    conf = find_address_conf(client_p->host,non_ident,
323 >                             &client_p->localClient->ip,
324 >                             client_p->localClient->aftype,
325 >                             client_p->localClient->passwd);
326    }
327  
328 <  uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
849 <  uhi[1] = client_p->host;
850 <  uhi[2] = client_p->sockhost;
851 <
852 <  rkconf = find_regexp_kline(uhi);
853 <
854 <  if (aconf != NULL)
328 >  if (conf != NULL)
329    {
330 <    if (IsConfClient(aconf) && !rkconf)
330 >    if (IsConfClient(conf))
331      {
332 <      conf = unmap_conf_item(aconf);
859 <
860 <      if (IsConfRedir(aconf))
332 >      if (IsConfRedir(conf))
333        {
334          sendto_one(client_p, form_str(RPL_REDIR),
335                     me.name, client_p->name,
336                     conf->name ? conf->name : "",
337 <                   aconf->port);
338 <        return(NOT_AUTHORIZED);
337 >                   conf->port);
338 >        return NOT_AUTHORIZED;
339        }
340  
341 <      if (IsConfDoIdentd(aconf))
342 <        SetNeedId(client_p);
341 >      if (IsConfDoIdentd(conf))
342 >        SetNeedId(client_p);
343  
344        /* Thanks for spoof idea amm */
345 <      if (IsConfDoSpoofIp(aconf))
345 >      if (IsConfDoSpoofIp(conf))
346        {
347 <        conf = unmap_conf_item(aconf);
876 <
877 <        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
347 >        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(conf))
348            sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
349                                 "%s spoofing: %s as %s",
350                                 client_p->name, client_p->host, conf->name);
351          strlcpy(client_p->host, conf->name, sizeof(client_p->host));
352 <        SetIPSpoof(client_p);
352 >        AddFlag(client_p, FLAGS_IP_SPOOFING | FLAGS_AUTH_SPOOF);
353        }
354  
355 <      return(attach_iline(client_p, conf));
355 >      return attach_iline(client_p, conf);
356      }
357 <    else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
357 >    else if (IsConfKill(conf) || (ConfigFileEntry.glines && IsConfGline(conf)))
358      {
359 <      /* XXX */
890 <      aconf = rkconf ? rkconf : aconf;
891 <      if (IsConfGline(aconf))
359 >      if (IsConfGline(conf))
360          sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
361                     client_p->name);
362        sendto_one(client_p, ":%s NOTICE %s :*** Banned: %s",
363 <                 me.name, client_p->name, aconf->reason);
364 <      return(BANNED_CLIENT);
363 >                 me.name, client_p->name, conf->reason);
364 >      return BANNED_CLIENT;
365      }
366    }
367  
368 <  return(NOT_AUTHORIZED);
368 >  return NOT_AUTHORIZED;
369   }
370  
371   /* attach_iline()
# Line 908 | Line 376 | verify_access(struct Client *client_p, c
376   * side effects - do actual attach
377   */
378   static int
379 < attach_iline(struct Client *client_p, struct ConfItem *conf)
379 > attach_iline(struct Client *client_p, struct MaskItem *conf)
380   {
381 <  struct AccessItem *aconf;
914 <  struct ClassItem *aclass;
381 >  struct ClassItem *class = NULL;
382    struct ip_entry *ip_found;
383    int a_limit_reached = 0;
384 <  int local = 0, global = 0, ident = 0;
384 >  unsigned int local = 0, global = 0, ident = 0;
385  
386    ip_found = find_or_add_ip(&client_p->localClient->ip);
387    ip_found->count++;
388    SetIpHash(client_p);
389  
390 <  aconf = map_to_conf(conf);
924 <  if (aconf->class_ptr == NULL)
390 >  if (conf->class == NULL)
391      return NOT_AUTHORIZED;  /* If class is missing, this is best */
392  
393 <  aclass = map_to_conf(aconf->class_ptr);
393 >  class = conf->class;
394  
395    count_user_host(client_p->username, client_p->host,
396                    &global, &local, &ident);
# Line 933 | Line 399 | attach_iline(struct Client *client_p, st
399     * setting a_limit_reached if any limit is reached.
400     * - Dianora
401     */
402 <  if (aclass->max_total != 0 && aclass->curr_user_count >= aclass->max_total)
402 >  if (class->max_total != 0 && class->ref_count >= class->max_total)
403      a_limit_reached = 1;
404 <  else if (aclass->max_perip != 0 && ip_found->count > aclass->max_perip)
404 >  else if (class->max_perip != 0 && ip_found->count > class->max_perip)
405      a_limit_reached = 1;
406 <  else if (aclass->max_local != 0 && local >= aclass->max_local)
406 >  else if (class->max_local != 0 && local >= class->max_local)
407      a_limit_reached = 1;
408 <  else if (aclass->max_global != 0 && global >= aclass->max_global)
408 >  else if (class->max_global != 0 && global >= class->max_global)
409      a_limit_reached = 1;
410 <  else if (aclass->max_ident != 0 && ident >= aclass->max_ident &&
410 >  else if (class->max_ident != 0 && ident >= class->max_ident &&
411             client_p->username[0] != '~')
412      a_limit_reached = 1;
413  
414    if (a_limit_reached)
415    {
416 <    if (!IsConfExemptLimits(aconf))
416 >    if (!IsConfExemptLimits(conf))
417        return TOO_MANY;   /* Already at maximum allowed */
418  
419      sendto_one(client_p,
# Line 968 | Line 434 | attach_iline(struct Client *client_p, st
434   void
435   init_ip_hash_table(void)
436   {
437 <  ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
972 <    2 * hard_fdlimit);
437 >  ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
438    memset(ip_hash_table, 0, sizeof(ip_hash_table));
439   }
440  
# Line 1018 | Line 483 | find_or_add_ip(struct irc_ssaddr *ip_in)
483    if (ip_entries_count >= 2 * hard_fdlimit)
484      garbage_collect_ip_entries();
485  
486 <  newptr = BlockHeapAlloc(ip_entry_heap);
486 >  newptr = mp_pool_get(ip_entry_pool);
487 >  memset(newptr, 0, sizeof(*newptr));
488    ip_entries_count++;
489    memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
490  
# Line 1069 | Line 535 | remove_one_ip(struct irc_ssaddr *ip_in)
535      if (ptr->count > 0)
536        ptr->count--;
537      if (ptr->count == 0 &&
538 <        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
538 >        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
539      {
540        if (last_ptr != NULL)
541 <        last_ptr->next = ptr->next;
541 >        last_ptr->next = ptr->next;
542        else
543 <        ip_hash_table[hash_index] = ptr->next;
543 >        ip_hash_table[hash_index] = ptr->next;
544  
545 <      BlockHeapFree(ip_entry_heap, ptr);
545 >      mp_pool_release(ptr);
546        ip_entries_count--;
547        return;
548      }
# Line 1179 | Line 645 | garbage_collect_ip_entries(void)
645            last_ptr->next = ptr->next;
646          else
647            ip_hash_table[i] = ptr->next;
648 <        BlockHeapFree(ip_entry_heap, ptr);
648 >        mp_pool_release(ptr);
649          ip_entries_count--;
650        }
651        else
# Line 1196 | Line 662 | garbage_collect_ip_entries(void)
662   * side effects - Disassociate configuration from the client.
663   *                Also removes a class from the list if marked for deleting.
664   */
665 < int
666 < detach_conf(struct Client *client_p, ConfType type)
665 > void
666 > detach_conf(struct Client *client_p, enum maskitem_type type)
667   {
668 <  dlink_node *ptr, *next_ptr;
1203 <  struct ConfItem *conf;
1204 <  struct ClassItem *aclass;
1205 <  struct AccessItem *aconf;
1206 <  struct ConfItem *aclass_conf;
668 >  dlink_node *ptr = NULL, *next_ptr = NULL;
669  
670    DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
671    {
672 <    conf = ptr->data;
1211 <
1212 <    if (type == CONF_TYPE || conf->type == type)
1213 <    {
1214 <      dlinkDelete(ptr, &client_p->localClient->confs);
1215 <      free_dlink_node(ptr);
1216 <
1217 <      switch (conf->type)
1218 <      {
1219 <      case CLIENT_TYPE:
1220 <      case OPER_TYPE:
1221 <      case SERVER_TYPE:
1222 <        aconf = map_to_conf(conf);
1223 <
1224 <        assert(aconf->clients > 0);
1225 <
1226 <        if ((aclass_conf = aconf->class_ptr) != NULL)
1227 <        {
1228 <          aclass = map_to_conf(aclass_conf);
672 >    struct MaskItem *conf = ptr->data;
673  
674 <          assert(aclass->curr_user_count > 0);
674 >    assert(conf->type & (CONF_CLIENT | CONF_OPER | CONF_SERVER));
675 >    assert(conf->ref_count > 0);
676 >    assert(conf->class->ref_count > 0);
677  
678 <          if (conf->type == CLIENT_TYPE)
679 <            remove_from_cidr_check(&client_p->localClient->ip, aclass);
1234 <          if (--aclass->curr_user_count == 0 && aclass->active == 0)
1235 <            delete_conf_item(aclass_conf);
1236 <        }
678 >    if (!(conf->type & type))
679 >      continue;
680  
681 <        if (--aconf->clients == 0 && IsConfIllegal(aconf))
682 <          delete_conf_item(conf);
681 >    dlinkDelete(ptr, &client_p->localClient->confs);
682 >    free_dlink_node(ptr);
683  
684 <        break;
685 <      default:
1243 <        break;
1244 <      }
684 >    if (conf->type == CONF_CLIENT)
685 >      remove_from_cidr_check(&client_p->localClient->ip, conf->class);
686  
687 <      if (type != CONF_TYPE)
688 <        return 0;
687 >    if (--conf->class->ref_count == 0 && conf->class->active == 0)
688 >    {
689 >      class_free(conf->class);
690 >      conf->class = NULL;
691      }
1249  }
692  
693 <  return -1;
693 >    if (--conf->ref_count == 0 && conf->active == 0)
694 >      conf_free(conf);
695 >  }
696   }
697  
698   /* attach_conf()
# Line 1262 | Line 706 | detach_conf(struct Client *client_p, Con
706   *                attachment if there was an old one...
707   */
708   int
709 < attach_conf(struct Client *client_p, struct ConfItem *conf)
709 > attach_conf(struct Client *client_p, struct MaskItem *conf)
710   {
1267  struct AccessItem *aconf = map_to_conf(conf);
1268  struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1269
711    if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
712      return 1;
713  
714 <  if (IsConfIllegal(aconf)) /* TBV: can't happen */
715 <    return NOT_AUTHORIZED;
716 <
1276 <  if (conf->type == CLIENT_TYPE)
1277 <    if (cidr_limit_reached(IsConfExemptLimits(aconf),
1278 <                           &client_p->localClient->ip, aclass))
714 >  if (conf->type == CONF_CLIENT)
715 >    if (cidr_limit_reached(IsConfExemptLimits(conf),
716 >                           &client_p->localClient->ip, conf->class))
717        return TOO_MANY;    /* Already at maximum allowed */
718  
719 <  aclass->curr_user_count++;
720 <  aconf->clients++;
719 >  conf->class->ref_count++;
720 >  conf->ref_count++;
721  
722    dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
723  
# Line 1299 | Line 737 | attach_connect_block(struct Client *clie
737                       const char *host)
738   {
739    dlink_node *ptr;
740 <  struct ConfItem *conf;
1303 <  struct AccessItem *aconf;
740 >  struct MaskItem *conf = NULL;
741  
742    assert(client_p != NULL);
743    assert(host != NULL);
# Line 1311 | Line 748 | attach_connect_block(struct Client *clie
748    DLINK_FOREACH(ptr, server_items.head)
749    {
750      conf = ptr->data;
1314    aconf = map_to_conf(conf);
751  
752 <    if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
752 >    if (match(conf->name, name) || match(conf->host, host))
753        continue;
754  
755      attach_conf(client_p, conf);
# Line 1323 | Line 759 | attach_connect_block(struct Client *clie
759    return 0;
760   }
761  
1326 /* find_conf_exact()
1327 *
1328 * inputs       - type of ConfItem
1329 *              - pointer to name to find
1330 *              - pointer to username to find
1331 *              - pointer to host to find
1332 * output       - NULL or pointer to conf found
1333 * side effects - find a conf entry which matches the hostname
1334 *                and has the same name.
1335 */
1336 struct ConfItem *
1337 find_conf_exact(ConfType type, const char *name, const char *user,
1338                const char *host)
1339 {
1340  dlink_node *ptr;
1341  dlink_list *list_p;
1342  struct ConfItem *conf = NULL;
1343  struct AccessItem *aconf;
1344
1345  /* Only valid for OPER_TYPE and ...? */
1346  list_p = map_to_list(type);
1347
1348  DLINK_FOREACH(ptr, (*list_p).head)
1349  {
1350    conf = ptr->data;
1351
1352    if (conf->name == NULL)
1353      continue;
1354    aconf = map_to_conf(conf);
1355    if (aconf->host == NULL)
1356      continue;
1357    if (irccmp(conf->name, name) != 0)
1358      continue;
1359
1360    /*
1361    ** Accept if the *real* hostname (usually sockethost)
1362    ** socket host) matches *either* host or name field
1363    ** of the configuration.
1364    */
1365    if (!match(aconf->host, host) || !match(aconf->user, user))
1366      continue;
1367    if (type == OPER_TYPE)
1368    {
1369      struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1370
1371      if (aconf->clients >= aclass->max_total)
1372        continue;
1373    }
1374
1375    return conf;
1376  }
1377
1378  return NULL;
1379 }
1380
762   /* find_conf_name()
763   *
764   * inputs       - pointer to conf link list to search
# Line 1387 | Line 768 | find_conf_exact(ConfType type, const cha
768   * side effects - find a conf entry which matches the name
769   *                and has the given mask.
770   */
771 < struct ConfItem *
772 < find_conf_name(dlink_list *list, const char *name, ConfType type)
771 > struct MaskItem *
772 > find_conf_name(dlink_list *list, const char *name, enum maskitem_type type)
773   {
774    dlink_node *ptr;
775 <  struct ConfItem* conf;
775 >  struct MaskItem* conf;
776  
777    DLINK_FOREACH(ptr, list->head)
778    {
# Line 1400 | Line 781 | find_conf_name(dlink_list *list, const c
781      if (conf->type == type)
782      {
783        if (conf->name && (irccmp(conf->name, name) == 0 ||
784 <                         match(conf->name, name)))
784 >                         !match(conf->name, name)))
785        return conf;
786      }
787    }
# Line 1415 | Line 796 | find_conf_name(dlink_list *list, const c
796   * side effects - none
797   */
798   static dlink_list *
799 < map_to_list(ConfType type)
799 > map_to_list(enum maskitem_type type)
800   {
801    switch(type)
802    {
803 <  case RXLINE_TYPE:
1423 <    return(&rxconf_items);
1424 <    break;
1425 <  case XLINE_TYPE:
803 >  case CONF_XLINE:
804      return(&xconf_items);
805      break;
806 <  case ULINE_TYPE:
806 >  case CONF_ULINE:
807      return(&uconf_items);
808      break;
809 <  case NRESV_TYPE:
809 >  case CONF_NRESV:
810      return(&nresv_items);
811      break;
812 <  case OPER_TYPE:
812 >  case CONF_CRESV:
813 >    return(&cresv_items);
814 >  case CONF_OPER:
815      return(&oconf_items);
816      break;
817 <  case CLASS_TYPE:
1438 <    return(&class_items);
1439 <    break;
1440 <  case SERVER_TYPE:
817 >  case CONF_SERVER:
818      return(&server_items);
819      break;
820 <  case SERVICE_TYPE:
820 >  case CONF_SERVICE:
821      return(&service_items);
822      break;
823 <  case CLUSTER_TYPE:
823 >  case CONF_CLUSTER:
824      return(&cluster_items);
825      break;
1449  case CONF_TYPE:
1450  case GLINE_TYPE:
1451  case KLINE_TYPE:
1452  case DLINE_TYPE:
1453  case CRESV_TYPE:
826    default:
827      return NULL;
828    }
# Line 1462 | Line 834 | map_to_list(ConfType type)
834   *              - pointer to name string to find
835   *              - pointer to user
836   *              - pointer to host
837 < *              - optional action to match on as well
838 < * output       - NULL or pointer to found struct MatchItem
837 > *              - optional flags to match on as well
838 > * output       - NULL or pointer to found struct MaskItem
839   * side effects - looks for a match on name field
840   */
841 < struct ConfItem *
842 < find_matching_name_conf(ConfType type, const char *name, const char *user,
843 <                        const char *host, int action)
841 > struct MaskItem *
842 > find_matching_name_conf(enum maskitem_type type, const char *name, const char *user,
843 >                        const char *host, unsigned int flags)
844   {
845    dlink_node *ptr=NULL;
846 <  struct ConfItem *conf=NULL;
1475 <  struct AccessItem *aconf=NULL;
1476 <  struct MatchItem *match_item=NULL;
846 >  struct MaskItem *conf=NULL;
847    dlink_list *list_p = map_to_list(type);
848  
849    switch (type)
850    {
851 < #ifdef HAVE_LIBPCRE
1482 <  case RXLINE_TYPE:
1483 <      DLINK_FOREACH(ptr, list_p->head)
1484 <      {
1485 <        conf = ptr->data;
1486 <        assert(conf->regexpname);
1487 <
1488 <        if (!ircd_pcre_exec(conf->regexpname, name))
1489 <          return conf;
1490 <      }
1491 <      break;
1492 < #endif
1493 <  case SERVICE_TYPE:
851 >  case CONF_SERVICE:
852      DLINK_FOREACH(ptr, list_p->head)
853      {
854        conf = ptr->data;
# Line 1502 | Line 860 | find_matching_name_conf(ConfType type, c
860      }
861      break;
862  
863 <  case XLINE_TYPE:
864 <  case ULINE_TYPE:
865 <  case NRESV_TYPE:
863 >  case CONF_XLINE:
864 >  case CONF_ULINE:
865 >  case CONF_NRESV:
866 >  case CONF_CRESV:
867      DLINK_FOREACH(ptr, list_p->head)
868      {
869        conf = ptr->data;
870  
1512      match_item = map_to_conf(conf);
871        if (EmptyString(conf->name))
872 <        continue;
873 <      if ((name != NULL) && match_esc(conf->name, name))
872 >        continue;
873 >      if ((name != NULL) && !match(conf->name, name))
874        {
875 <        if ((user == NULL && (host == NULL)))
876 <          return conf;
877 <        if ((match_item->action & action) != action)
875 >        if ((user == NULL && (host == NULL)))
876 >          return conf;
877 >        if ((conf->flags & flags) != flags)
878            continue;
879 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
880 <          return conf;
881 <        if (match(match_item->user, user) && match(match_item->host, host))
882 <          return conf;
879 >        if (EmptyString(conf->user) || EmptyString(conf->host))
880 >          return conf;
881 >        if (!match(conf->user, user) && !match(conf->host, host))
882 >          return conf;
883        }
884      }
885        break;
886  
887 <  case SERVER_TYPE:
887 >  case CONF_SERVER:
888      DLINK_FOREACH(ptr, list_p->head)
889      {
890        conf = ptr->data;
1533      aconf = map_to_conf(conf);
891  
892 <      if ((name != NULL) && match_esc(name, conf->name))
892 >      if ((name != NULL) && !match(name, conf->name))
893          return conf;
894 <      else if ((host != NULL) && match_esc(host, aconf->host))
894 >      else if ((host != NULL) && !match(host, conf->host))
895          return conf;
896      }
897      break;
# Line 1551 | Line 908 | find_matching_name_conf(ConfType type, c
908   *              - pointer to name string to find
909   *              - pointer to user
910   *              - pointer to host
911 < * output       - NULL or pointer to found struct MatchItem
911 > * output       - NULL or pointer to found struct MaskItem
912   * side effects - looks for an exact match on name field
913   */
914 < struct ConfItem *
915 < find_exact_name_conf(ConfType type, const struct Client *who, const char *name,
914 > struct MaskItem *
915 > find_exact_name_conf(enum maskitem_type type, const struct Client *who, const char *name,
916                       const char *user, const char *host)
917   {
918    dlink_node *ptr = NULL;
919 <  struct AccessItem *aconf;
920 <  struct ConfItem *conf;
1564 <  struct MatchItem *match_item;
1565 <  dlink_list *list_p;
1566 <
1567 <  list_p = map_to_list(type);
919 >  struct MaskItem *conf;
920 >  dlink_list *list_p = map_to_list(type);
921  
922    switch(type)
923    {
924 <  case RXLINE_TYPE:
925 <  case XLINE_TYPE:
926 <  case ULINE_TYPE:
927 <  case NRESV_TYPE:
924 >  case CONF_XLINE:
925 >  case CONF_ULINE:
926 >  case CONF_NRESV:
927 >  case CONF_CRESV:
928  
929      DLINK_FOREACH(ptr, list_p->head)
930      {
931        conf = ptr->data;
932 <      match_item = (struct MatchItem *)map_to_conf(conf);
932 >
933        if (EmptyString(conf->name))
934 <        continue;
934 >        continue;
935      
936        if (irccmp(conf->name, name) == 0)
937        {
938 <        if ((user == NULL && (host == NULL)))
939 <          return (conf);
940 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
941 <          return (conf);
942 <        if (match(match_item->user, user) && match(match_item->host, host))
943 <          return (conf);
938 >        if ((user == NULL && (host == NULL)))
939 >          return conf;
940 >        if (EmptyString(conf->user) || EmptyString(conf->host))
941 >          return conf;
942 >        if (!match(conf->user, user) && !match(conf->host, host))
943 >          return conf;
944        }
945      }
946      break;
947  
948 <  case OPER_TYPE:
948 >  case CONF_OPER:
949      DLINK_FOREACH(ptr, list_p->head)
950      {
951        conf = ptr->data;
1599      aconf = map_to_conf(conf);
952  
953        if (EmptyString(conf->name))
954          continue;
# Line 1605 | Line 957 | find_exact_name_conf(ConfType type, cons
957        {
958          if (!who)
959            return conf;
960 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
961 <          return conf;
962 <        if (match(aconf->user, who->username))
960 >        if (EmptyString(conf->user) || EmptyString(conf->host))
961 >          return NULL;
962 >        if (!match(conf->user, who->username))
963          {
964 <          switch (aconf->type)
964 >          switch (conf->htype)
965            {
966              case HM_HOST:
967 <              if (match(aconf->host, who->host) || match(aconf->host, who->sockhost))
968 <                return conf;
967 >              if (!match(conf->host, who->host) || !match(conf->host, who->sockhost))
968 >                if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
969 >                  return conf;
970                break;
971              case HM_IPV4:
972                if (who->localClient->aftype == AF_INET)
973 <                if (match_ipv4(&who->localClient->ip, &aconf->addr, aconf->bits))
974 <                  return conf;
973 >                if (match_ipv4(&who->localClient->ip, &conf->addr, conf->bits))
974 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
975 >                    return conf;
976                break;
977   #ifdef IPV6
978              case HM_IPV6:
979                if (who->localClient->aftype == AF_INET6)
980 <                if (match_ipv6(&who->localClient->ip, &aconf->addr, aconf->bits))
981 <                  return conf;
980 >                if (match_ipv6(&who->localClient->ip, &conf->addr, conf->bits))
981 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
982 >                    return conf;
983                break;
984   #endif
985              default:
# Line 1636 | Line 991 | find_exact_name_conf(ConfType type, cons
991  
992      break;
993  
994 <  case SERVER_TYPE:
994 >  case CONF_SERVER:
995      DLINK_FOREACH(ptr, list_p->head)
996      {
997        conf = ptr->data;
998 <      aconf = (struct AccessItem *)map_to_conf(conf);
998 >
999        if (EmptyString(conf->name))
1000 <        continue;
1000 >        continue;
1001      
1002        if (name == NULL)
1003        {
1004 <        if (EmptyString(aconf->host))
1005 <          continue;
1006 <        if (irccmp(aconf->host, host) == 0)
1007 <          return(conf);
1004 >        if (EmptyString(conf->host))
1005 >          continue;
1006 >        if (irccmp(conf->host, host) == 0)
1007 >          return conf;
1008        }
1009        else if (irccmp(conf->name, name) == 0)
1010 <      {
1656 <          return (conf);
1657 <      }
1010 >        return conf;
1011      }
1659    break;
1012  
1661  case CLASS_TYPE:
1662    DLINK_FOREACH(ptr, list_p->head)
1663    {
1664      conf = ptr->data;
1665      if (EmptyString(conf->name))
1666        continue;
1667    
1668      if (irccmp(conf->name, name) == 0)
1669        return (conf);
1670    }
1013      break;
1014  
1015    default:
1016      break;
1017    }
1018 <  return(NULL);
1018 >
1019 >  return NULL;
1020   }
1021  
1022   /* rehash()
# Line 1703 | Line 1046 | rehash(int sig)
1046  
1047    load_conf_modules();
1048  
1706  flush_deleted_I_P();
1707
1049    rehashed_klines = 1;
1709 /* XXX */
1710  if (ConfigLoggingEntry.use_logging)
1711    log_close_all();
1050  
1051 <  return(0);
1051 >  return 0;
1052   }
1053  
1054   /* set_default_conf()
# Line 1728 | Line 1066 | set_default_conf(void)
1066    /* verify init_class() ran, this should be an unnecessary check
1067     * but its not much work.
1068     */
1069 <  assert(class_default == (struct ConfItem *) class_items.tail->data);
1069 >  assert(class_default == class_get_list()->tail->data);
1070  
1071   #ifdef HAVE_LIBCRYPTO
1072    ServerInfo.rsa_private_key = NULL;
# Line 1738 | Line 1076 | set_default_conf(void)
1076    /* ServerInfo.name is not rehashable */
1077    /* ServerInfo.name = ServerInfo.name; */
1078    ServerInfo.description = NULL;
1079 <  DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1080 <  DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1079 >  ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1080 >  ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1081  
1082    memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1083    ServerInfo.specific_ipv4_vhost = 0;
# Line 1747 | Line 1085 | set_default_conf(void)
1085    ServerInfo.specific_ipv6_vhost = 0;
1086  
1087    ServerInfo.max_clients = MAXCLIENTS_MAX;
1088 +  ServerInfo.max_nick_length = 9;
1089 +  ServerInfo.max_topic_length = 80;
1090  
1091    ServerInfo.hub = 0;
1092    ServerInfo.dns_host.sin_addr.s_addr = 0;
# Line 1755 | Line 1095 | set_default_conf(void)
1095    AdminInfo.email = NULL;
1096    AdminInfo.description = NULL;
1097  
1098 <  log_close_all();
1098 >  log_del_all();
1099  
1100    ConfigLoggingEntry.use_logging = 1;
1101  
1102    ConfigChannel.disable_fake_channels = 0;
1763  ConfigChannel.restrict_channels = 0;
1103    ConfigChannel.knock_delay = 300;
1104    ConfigChannel.knock_delay_channel = 60;
1105    ConfigChannel.max_chans_per_user = 25;
1106    ConfigChannel.max_chans_per_oper = 50;
1768  ConfigChannel.quiet_on_ban = 1;
1107    ConfigChannel.max_bans = 25;
1108    ConfigChannel.default_split_user_count = 0;
1109    ConfigChannel.default_split_server_count = 0;
# Line 1776 | Line 1114 | set_default_conf(void)
1114    ConfigServerHide.links_delay = 300;
1115    ConfigServerHide.hidden = 0;
1116    ConfigServerHide.hide_servers = 0;
1117 <  DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1117 >  ConfigServerHide.hide_services = 0;
1118 >  ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
1119    ConfigServerHide.hide_server_ips = 0;
1120 +  ConfigServerHide.disable_remote_commands = 0;
1121  
1122    
1123 <  DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1123 >  ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1124    ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1125 +  ConfigFileEntry.cycle_on_host_change = 1;
1126    ConfigFileEntry.glines = 0;
1127    ConfigFileEntry.gline_time = 12 * 3600;
1128    ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
# Line 1792 | Line 1133 | set_default_conf(void)
1133    ConfigFileEntry.hide_spoof_ips = 1;
1134    ConfigFileEntry.ignore_bogus_ts = 0;
1135    ConfigFileEntry.disable_auth = 0;
1795  ConfigFileEntry.disable_remote = 0;
1136    ConfigFileEntry.kill_chase_time_limit = 90;
1137    ConfigFileEntry.default_floodcount = 8;
1138    ConfigFileEntry.failed_oper_notice = 1;
# Line 1811 | Line 1151 | set_default_conf(void)
1151    ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
1152    ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
1153    ConfigFileEntry.stats_P_oper_only = 0;
1154 +  ConfigFileEntry.stats_u_oper_only = 0;
1155    ConfigFileEntry.caller_id_wait = 60;
1156    ConfigFileEntry.opers_bypass_callerid = 0;
1157    ConfigFileEntry.pace_wait = 10;
# Line 1839 | Line 1180 | validate_conf(void)
1180      ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1181  
1182    if (ServerInfo.network_name == NULL)
1183 <    DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1183 >    ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1184  
1185    if (ServerInfo.network_desc == NULL)
1186 <    DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1186 >    ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1187  
1188    if (ConfigFileEntry.service_name == NULL)
1189 <    DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1189 >    ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1190  
1191    ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1192   }
# Line 1863 | Line 1204 | read_conf(FILE *file)
1204  
1205    set_default_conf(); /* Set default values prior to conf parsing */
1206    conf_parser_ctx.pass = 1;
1207 <  yyparse();          /* pick up the classes first */
1207 >  yyparse();          /* pick up the classes first */
1208  
1209    rewind(file);
1210  
# Line 1871 | Line 1212 | read_conf(FILE *file)
1212    yyparse();          /* Load the values from the conf */
1213    validate_conf();    /* Check to make sure some values are still okay. */
1214                        /* Some global values are also loaded here. */
1215 <  check_class();      /* Make sure classes are valid */
1215 >  class_delete_marked();      /* Make sure classes are valid */
1216   }
1217  
1218   /* lookup_confhost()
# Line 1879 | Line 1220 | read_conf(FILE *file)
1220   * start DNS lookups of all hostnames in the conf
1221   * line and convert an IP addresses in a.b.c.d number for to IP#s.
1222   */
1223 < static void
1224 < lookup_confhost(struct ConfItem *conf)
1223 > void
1224 > lookup_confhost(struct MaskItem *conf)
1225   {
1885  struct AccessItem *aconf;
1226    struct addrinfo hints, *res;
1227  
1888  aconf = map_to_conf(conf);
1889
1890  if (has_wildcards(aconf->host))
1891  {
1892    ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
1893         aconf->host, conf->name);
1894    return;
1895  }
1896
1228    /* Do name lookup now on hostnames given and store the
1229     * ip numbers in conf structure.
1230     */
# Line 1905 | Line 1236 | lookup_confhost(struct ConfItem *conf)
1236    /* Get us ready for a bind() and don't bother doing dns lookup */
1237    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1238  
1239 <  if (getaddrinfo(aconf->host, NULL, &hints, &res))
1239 >  if (getaddrinfo(conf->host, NULL, &hints, &res))
1240    {
1241 <    conf_dns_lookup(aconf);
1241 >    conf_dns_lookup(conf);
1242      return;
1243    }
1244  
1245    assert(res != NULL);
1246  
1247 <  memcpy(&aconf->addr, res->ai_addr, res->ai_addrlen);
1248 <  aconf->addr.ss_len = res->ai_addrlen;
1249 <  aconf->addr.ss.ss_family = res->ai_family;
1247 >  memcpy(&conf->addr, res->ai_addr, res->ai_addrlen);
1248 >  conf->addr.ss_len = res->ai_addrlen;
1249 >  conf->addr.ss.ss_family = res->ai_family;
1250 >
1251    freeaddrinfo(res);
1252   }
1253  
# Line 1930 | Line 1262 | int
1262   conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1263   {
1264    struct ip_entry *ip_found;
1265 <  struct AccessItem *aconf = find_dline_conf(addr, aftype);
1265 >  struct MaskItem *conf = find_dline_conf(addr, aftype);
1266  
1267    /* DLINE exempt also gets you out of static limits/pacing... */
1268 <  if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1268 >  if (conf && (conf->type == CONF_EXEMPT))
1269      return 0;
1270  
1271 <  if (aconf != NULL)
1271 >  if (conf != NULL)
1272      return BANNED_CLIENT;
1273  
1274    ip_found = find_or_add_ip(addr);
# Line 1952 | Line 1284 | conf_connect_allowed(struct irc_ssaddr *
1284    return 0;
1285   }
1286  
1955 static struct AccessItem *
1956 find_regexp_kline(const char *uhi[])
1957 {
1958 #ifdef HAVE_LIBPCRE
1959  const dlink_node *ptr = NULL;
1960
1961  DLINK_FOREACH(ptr, rkconf_items.head)
1962  {
1963    struct AccessItem *aptr = map_to_conf(ptr->data);
1964
1965    assert(aptr->regexuser);
1966    assert(aptr->regexhost);
1967
1968    if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
1969        (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
1970         !ircd_pcre_exec(aptr->regexhost, uhi[2])))
1971      return aptr;
1972  }
1973 #endif
1974  return NULL;
1975 }
1976
1287   /* find_kill()
1288   *
1289   * inputs       - pointer to client structure
1290 < * output       - pointer to struct AccessItem if found
1290 > * output       - pointer to struct MaskItem if found
1291   * side effects - See if this user is klined already,
1292 < *                and if so, return struct AccessItem pointer
1292 > *                and if so, return struct MaskItem pointer
1293   */
1294 < struct AccessItem *
1294 > struct MaskItem *
1295   find_kill(struct Client *client_p)
1296   {
1297 <  struct AccessItem *aconf = NULL;
1988 <  const char *uhi[3];
1989 <
1990 <  uhi[0] = client_p->username;
1991 <  uhi[1] = client_p->host;
1992 <  uhi[2] = client_p->sockhost;
1297 >  struct MaskItem *conf = NULL;
1298  
1299    assert(client_p != NULL);
1300  
1301 <  aconf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1302 <                               CONF_KLINE, client_p->localClient->aftype,
1303 <                               client_p->username, NULL, 1);
1304 <  if (aconf == NULL)
2000 <    aconf = find_regexp_kline(uhi);
2001 <
2002 <  return aconf;
1301 >  conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1302 >                              CONF_KLINE, client_p->localClient->aftype,
1303 >                              client_p->username, NULL, 1);
1304 >  return conf;
1305   }
1306  
1307 < struct AccessItem *
1307 > struct MaskItem *
1308   find_gline(struct Client *client_p)
1309   {
1310 <  struct AccessItem *aconf;
1310 >  struct MaskItem *conf;
1311  
1312    assert(client_p != NULL);
1313  
1314 <  aconf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1315 <                               CONF_GLINE, client_p->localClient->aftype,
1316 <                               client_p->username, NULL, 1);
1317 <  return aconf;
2016 < }
2017 <
2018 < /* add_temp_line()
2019 < *
2020 < * inputs        - pointer to struct ConfItem
2021 < * output        - none
2022 < * Side effects  - links in given struct ConfItem into
2023 < *                 temporary *line link list
2024 < */
2025 < void
2026 < add_temp_line(struct ConfItem *conf)
2027 < {
2028 <  if (conf->type == XLINE_TYPE)
2029 <  {
2030 <    conf->flags |= CONF_FLAGS_TEMPORARY;
2031 <    dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2032 <  }
2033 <  else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2034 <  {
2035 <    conf->flags |= CONF_FLAGS_TEMPORARY;
2036 <    dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2037 <  }
1314 >  conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1315 >                              CONF_GLINE, client_p->localClient->aftype,
1316 >                              client_p->username, NULL, 1);
1317 >  return conf;
1318   }
1319  
1320   /* cleanup_tklines()
# Line 2048 | Line 1328 | void
1328   cleanup_tklines(void *notused)
1329   {
1330    hostmask_expire_temporary();
1331 <  expire_tklines(&temporary_xlines);
1332 <  expire_tklines(&temporary_resv);
1331 >  expire_tklines(&xconf_items);
1332 >  expire_tklines(&nresv_items);
1333 >  expire_tklines(&cresv_items);
1334   }
1335  
1336   /* expire_tklines()
# Line 2063 | Line 1344 | expire_tklines(dlink_list *tklist)
1344   {
1345    dlink_node *ptr;
1346    dlink_node *next_ptr;
1347 <  struct ConfItem *conf;
2067 <  struct MatchItem *xconf;
2068 <  struct MatchItem *nconf;
2069 <  struct ResvChannel *cconf;
1347 >  struct MaskItem *conf;
1348  
1349    DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
1350    {
1351      conf = ptr->data;
1352  
1353 <    if (conf->type == XLINE_TYPE)
1353 >    if (!conf->until || conf->until > CurrentTime)
1354 >      continue;
1355 >
1356 >    if (conf->type == CONF_XLINE)
1357      {
1358 <      xconf = (struct MatchItem *)map_to_conf(conf);
1359 <      if (xconf->hold <= CurrentTime)
2079 <      {
2080 <        if (ConfigFileEntry.tkline_expire_notices)
2081 <          sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1358 >      if (ConfigFileEntry.tkline_expire_notices)
1359 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1360                                 "Temporary X-line for [%s] expired", conf->name);
1361 <        dlinkDelete(ptr, tklist);
2084 <        free_dlink_node(ptr);
2085 <        delete_conf_item(conf);
2086 <      }
1361 >      conf_free(conf);
1362      }
1363 <    else if (conf->type == NRESV_TYPE)
1363 >    else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1364      {
1365 <      nconf = (struct MatchItem *)map_to_conf(conf);
1366 <      if (nconf->hold <= CurrentTime)
2092 <      {
2093 <        if (ConfigFileEntry.tkline_expire_notices)
2094 <          sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1365 >      if (ConfigFileEntry.tkline_expire_notices)
1366 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1367                                 "Temporary RESV for [%s] expired", conf->name);
1368 <        dlinkDelete(ptr, tklist);
2097 <        free_dlink_node(ptr);
2098 <        delete_conf_item(conf);
2099 <      }
2100 <    }
2101 <    else if (conf->type == CRESV_TYPE)
2102 <    {
2103 <      cconf = (struct ResvChannel *)map_to_conf(conf);
2104 <      if (cconf->hold <= CurrentTime)
2105 <      {
2106 <        if (ConfigFileEntry.tkline_expire_notices)
2107 <          sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2108 <                               "Temporary RESV for [%s] expired", cconf->name);
2109 <        delete_channel_resv(cconf);
2110 <      }
1368 >      conf_free(conf);
1369      }
1370    }
1371   }
# Line 2120 | Line 1378 | expire_tklines(dlink_list *tklist)
1378   */
1379   static const struct oper_privs
1380   {
1381 <  const unsigned int oprivs;
1381 >  const unsigned int flag;
1382    const unsigned char c;
1383   } flag_list[] = {
1384 <  { OPER_FLAG_ADMIN,       'A' },
1385 <  { OPER_FLAG_REMOTEBAN,   'B' },
1386 <  { OPER_FLAG_DIE,         'D' },
1387 <  { OPER_FLAG_GLINE,       'G' },
1388 <  { OPER_FLAG_REHASH,      'H' },
1389 <  { OPER_FLAG_K,           'K' },
1390 <  { OPER_FLAG_OPERWALL,    'L' },
1391 <  { OPER_FLAG_N,           'N' },
1392 <  { OPER_FLAG_GLOBAL_KILL, 'O' },
1393 <  { OPER_FLAG_REMOTE,      'R' },
1394 <  { OPER_FLAG_OPER_SPY,    'S' },
1395 <  { OPER_FLAG_UNKLINE,     'U' },
1396 <  { OPER_FLAG_X,           'X' },
1384 >  { OPER_FLAG_ADMIN,          'A' },
1385 >  { OPER_FLAG_REMOTEBAN,      'B' },
1386 >  { OPER_FLAG_DIE,            'D' },
1387 >  { OPER_FLAG_GLINE,          'G' },
1388 >  { OPER_FLAG_REHASH,         'H' },
1389 >  { OPER_FLAG_K,              'K' },
1390 >  { OPER_FLAG_OPERWALL,       'L' },
1391 >  { OPER_FLAG_KILL,           'N' },
1392 >  { OPER_FLAG_KILL_REMOTE,    'O' },
1393 >  { OPER_FLAG_CONNECT,        'P' },
1394 >  { OPER_FLAG_CONNECT_REMOTE, 'Q' },
1395 >  { OPER_FLAG_SQUIT,          'R' },
1396 >  { OPER_FLAG_SQUIT_REMOTE,   'S' },
1397 >  { OPER_FLAG_UNKLINE,        'U' },
1398 >  { OPER_FLAG_X,              'X' },
1399    { 0, '\0' }
1400   };
1401  
# Line 2144 | Line 1404 | oper_privs_as_string(const unsigned int
1404   {
1405    static char privs_out[16];
1406    char *privs_ptr = privs_out;
1407 <  unsigned int i = 0;
1407 >  const struct oper_privs *opriv = flag_list;
1408  
1409 <  for (; flag_list[i].oprivs; ++i)
1409 >  for (; opriv->flag; ++opriv)
1410    {
1411 <    if (port & flag_list[i].oprivs)
1412 <      *privs_ptr++ = flag_list[i].c;
1411 >    if (port & opriv->flag)
1412 >      *privs_ptr++ = opriv->c;
1413      else
1414 <      *privs_ptr++ = ToLowerTab[flag_list[i].c];
1414 >      *privs_ptr++ = ToLower(opriv->c);
1415    }
1416  
1417    *privs_ptr = '\0';
# Line 2176 | Line 1436 | get_oper_name(const struct Client *clien
1436    {
1437      if ((cnode = client_p->localClient->confs.head))
1438      {
1439 <      struct ConfItem *conf = cnode->data;
2180 <      const struct AccessItem *aconf = map_to_conf(conf);
1439 >      struct MaskItem *conf = cnode->data;
1440  
1441 <      if (IsConfOperator(aconf))
1441 >      if (IsConfOperator(conf))
1442        {
1443 <        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1443 >        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1444                   client_p->username, client_p->host, conf->name);
1445 <        return buffer;
1445 >        return buffer;
1446        }
1447      }
1448  
# Line 2194 | Line 1453 | get_oper_name(const struct Client *clien
1453    }
1454  
1455    snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1456 <           client_p->username, client_p->host, client_p->servptr->name);
1456 >           client_p->username, client_p->host, client_p->servptr->name);
1457    return buffer;
1458   }
1459  
# Line 2212 | Line 1471 | read_conf_files(int cold)
1471    char chanlimit[32];
1472  
1473    conf_parser_ctx.boot = cold;
1474 <  filename = get_conf_name(CONF_TYPE);
1474 >  filename = ConfigFileEntry.configfile;
1475  
1476    /* We need to know the initial filename for the yyerror() to report
1477       FIXME: The full path is in conffilenamebuf first time since we
# Line 2233 | Line 1492 | read_conf_files(int cold)
1492      else
1493      {
1494        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1495 <                           "Unable to read configuration file '%s': %s",
1496 <                           filename, strerror(errno));
1495 >                           "Unable to read configuration file '%s': %s",
1496 >                           filename, strerror(errno));
1497        return;
1498      }
1499    }
# Line 2245 | Line 1504 | read_conf_files(int cold)
1504    read_conf(conf_parser_ctx.conf_file);
1505    fclose(conf_parser_ctx.conf_file);
1506  
1507 +  log_reopen_all();
1508 +
1509 +  add_isupport("NICKLEN", NULL, ServerInfo.max_nick_length);
1510    add_isupport("NETWORK", ServerInfo.network_name, -1);
1511 <  snprintf(chanmodes, sizeof(chanmodes), "beI:%d",
1512 <           ConfigChannel.max_bans);
1511 >
1512 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1513    add_isupport("MAXLIST", chanmodes, -1);
1514    add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
2253
1515    add_isupport("CHANTYPES", "#", -1);
1516  
1517    snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1518 <           ConfigChannel.max_chans_per_user);
1518 >           ConfigChannel.max_chans_per_user);
1519    add_isupport("CHANLIMIT", chanlimit, -1);
1520 <  snprintf(chanmodes, sizeof(chanmodes), "%s",
2260 <           "beI,k,l,imnprstORS");
1520 >  snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,imnprstORS");
1521    add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
1522 <
2263 <  add_isupport("EXCEPTS", "e", -1);
2264 <  add_isupport("INVEX", "I", -1);
1522 >  add_isupport("TOPICLEN", NULL, ServerInfo.max_topic_length);
1523    add_isupport("CHANMODES", chanmodes, -1);
1524  
1525    /*
# Line 2269 | Line 1527 | read_conf_files(int cold)
1527     * on strlen(form_str(RPL_ISUPPORT))
1528     */
1529    rebuild_isupport_message_line();
2272
2273  parse_conf_file(KLINE_TYPE, cold);
2274  parse_conf_file(DLINE_TYPE, cold);
2275  parse_conf_file(XLINE_TYPE, cold);
2276  parse_conf_file(NRESV_TYPE, cold);
2277  parse_conf_file(CRESV_TYPE, cold);
2278 }
2279
2280 /* parse_conf_file()
2281 *
2282 * inputs       - type of conf file to parse
2283 * output       - none
2284 * side effects - conf file for givenconf type is opened and read then parsed
2285 */
2286 static void
2287 parse_conf_file(int type, int cold)
2288 {
2289  FILE *file = NULL;
2290  const char *filename = get_conf_name(type);
2291
2292  if ((file = fopen(filename, "r")) == NULL)
2293  {
2294    if (cold)
2295      ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2296           filename, strerror(errno));
2297    else
2298      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2299                    "Unable to read configuration file '%s': %s",
2300                           filename, strerror(errno));
2301  }
2302  else
2303  {
2304    parse_csv_file(file, type);
2305    fclose(file);
2306  }
1530   }
1531  
1532   /* clear_out_old_conf()
# Line 2316 | Line 1539 | static void
1539   clear_out_old_conf(void)
1540   {
1541    dlink_node *ptr = NULL, *next_ptr = NULL;
1542 <  struct ConfItem *conf;
2320 <  struct AccessItem *aconf;
2321 <  struct ClassItem *cltmp;
1542 >  struct MaskItem *conf;
1543    dlink_list *free_items [] = {
1544      &server_items,   &oconf_items,
1545 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1546 <     &nresv_items, &cluster_items,  &service_items, NULL
1545 >     &uconf_items,   &xconf_items,
1546 >     &nresv_items, &cluster_items,  &service_items, &cresv_items, NULL
1547    };
1548  
1549    dlink_list ** iterator = free_items; /* C is dumb */
# Line 2336 | Line 1557 | clear_out_old_conf(void)
1557      DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1558      {
1559        conf = ptr->data;
2339      /* XXX This is less than pretty */
2340      if (conf->type == SERVER_TYPE)
2341      {
2342        aconf = map_to_conf(conf);
1560  
1561 <        if (aconf->clients != 0)
2345 <        {
2346 <          SetConfIllegal(aconf);
2347 <          dlinkDelete(&conf->node, &server_items);
2348 <        }
2349 <        else
2350 <        {
2351 <          delete_conf_item(conf);
2352 <        }
2353 <      }
2354 <      else if (conf->type == OPER_TYPE)
2355 <      {
2356 <        aconf = map_to_conf(conf);
1561 >      dlinkDelete(&conf->node, map_to_list(conf->type));
1562  
1563 <        if (aconf->clients != 0)
1564 <        {
2360 <          SetConfIllegal(aconf);
2361 <          dlinkDelete(&conf->node, &oconf_items);
2362 <        }
2363 <        else
2364 <        {
2365 <          delete_conf_item(conf);
2366 <        }
2367 <      }
2368 <      else if (conf->type == XLINE_TYPE  ||
2369 <               conf->type == RXLINE_TYPE ||
2370 <               conf->type == RKLINE_TYPE)
1563 >      /* XXX This is less than pretty */
1564 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1565        {
1566 <        /* temporary (r)xlines are also on
1567 <         * the (r)xconf items list */
2374 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2375 <          continue;
2376 <
2377 <        delete_conf_item(conf);
1566 >        if (!conf->ref_count)
1567 >          conf_free(conf);
1568        }
1569 <      else
1569 >      else if (conf->type == CONF_XLINE)
1570        {
1571 <          delete_conf_item(conf);
1571 >        if (!conf->until)
1572 >          conf_free(conf);
1573        }
1574 +      else
1575 +        conf_free(conf);
1576      }
1577    }
1578  
1579 +  motd_clear();
1580 +
1581    /*
1582     * don't delete the class table, rather mark all entries
1583 <   * for deletion. The table is cleaned up by check_class. - avalon
1583 >   * for deletion. The table is cleaned up by class_delete_marked. - avalon
1584     */
1585 <  DLINK_FOREACH(ptr, class_items.head)
2391 <  {
2392 <    cltmp = map_to_conf(ptr->data);
2393 <
2394 <    if (ptr != class_items.tail)  /* never mark the "default" class */
2395 <      cltmp->active = 0;
2396 <  }
1585 >  class_mark_for_deletion();
1586  
1587    clear_out_address_conf();
1588  
# Line 2429 | Line 1618 | clear_out_old_conf(void)
1618                                                 SSL_OP_NO_TLSv1);
1619   #endif
1620  
2432  /* clean out old resvs from the conf */
2433  clear_conf_resv();
2434
1621    /* clean out AdminInfo */
1622    MyFree(AdminInfo.name);
1623    AdminInfo.name = NULL;
# Line 2440 | Line 1626 | clear_out_old_conf(void)
1626    MyFree(AdminInfo.description);
1627    AdminInfo.description = NULL;
1628  
2443  /* operator{} and class{} blocks are freed above */
1629    /* clean out listeners */
1630    close_listeners();
1631  
2447  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2448   * exempt{} and gecos{} blocks are freed above too
2449   */
2450
1632    /* clean out general */
1633    MyFree(ConfigFileEntry.service_name);
1634    ConfigFileEntry.service_name = NULL;
2454
2455  delete_isupport("INVEX");
2456  delete_isupport("EXCEPTS");
2457 }
2458
2459 /* flush_deleted_I_P()
2460 *
2461 * inputs       - none
2462 * output       - none
2463 * side effects - This function removes I/P conf items
2464 */
2465 static void
2466 flush_deleted_I_P(void)
2467 {
2468  dlink_node *ptr;
2469  dlink_node *next_ptr;
2470  struct ConfItem *conf;
2471  struct AccessItem *aconf;
2472  dlink_list * free_items [] = {
2473    &server_items, &oconf_items, NULL
2474  };
2475  dlink_list ** iterator = free_items; /* C is dumb */
2476
2477  /* flush out deleted I and P lines
2478   * although still in use.
2479   */
2480  for (; *iterator != NULL; iterator++)
2481  {
2482    DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2483    {
2484      conf = ptr->data;
2485      aconf = (struct AccessItem *)map_to_conf(conf);
2486
2487      if (IsConfIllegal(aconf))
2488      {
2489        dlinkDelete(ptr, *iterator);
2490
2491        if (aconf->clients == 0)
2492          delete_conf_item(conf);
2493      }
2494    }
2495  }
2496 }
2497
2498 /* get_conf_name()
2499 *
2500 * inputs       - type of conf file to return name of file for
2501 * output       - pointer to filename for type of conf
2502 * side effects - none
2503 */
2504 const char *
2505 get_conf_name(ConfType type)
2506 {
2507  switch (type)
2508  {
2509    case CONF_TYPE:
2510      return ConfigFileEntry.configfile;
2511      break;
2512    case KLINE_TYPE:
2513      return ConfigFileEntry.klinefile;
2514      break;
2515    case DLINE_TYPE:
2516      return ConfigFileEntry.dlinefile;
2517      break;
2518    case XLINE_TYPE:
2519      return ConfigFileEntry.xlinefile;
2520      break;
2521    case CRESV_TYPE:
2522      return ConfigFileEntry.cresvfile;
2523      break;
2524    case NRESV_TYPE:
2525      return ConfigFileEntry.nresvfile;
2526      break;
2527    default:
2528      return NULL;  /* This should NEVER HAPPEN since we call this function
2529                       only with the above values, this will cause us to core
2530                       at some point if this happens so we know where it was */
2531  }
2532 }
2533
2534 #define BAD_PING (-1)
2535
2536 /* get_conf_ping()
2537 *
2538 * inputs       - pointer to struct AccessItem
2539 *              - pointer to a variable that receives ping warning time
2540 * output       - ping frequency
2541 * side effects - NONE
2542 */
2543 static int
2544 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2545 {
2546  struct ClassItem *aclass;
2547  struct AccessItem *aconf;
2548
2549  if (conf != NULL)
2550  {
2551    aconf = (struct AccessItem *)map_to_conf(conf);
2552    if (aconf->class_ptr != NULL)
2553    {
2554      aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2555      *pingwarn = aclass->ping_warning;
2556      return aclass->ping_freq;
2557    }
2558  }
2559
2560  return BAD_PING;
2561 }
2562
2563 /* get_client_class()
2564 *
2565 * inputs       - pointer to client struct
2566 * output       - pointer to name of class
2567 * side effects - NONE
2568 */
2569 const char *
2570 get_client_class(struct Client *target_p)
2571 {
2572  dlink_node *cnode = NULL;
2573  struct AccessItem *aconf = NULL;
2574
2575  assert(!IsMe(target_p));
2576
2577  if ((cnode = target_p->localClient->confs.head))
2578  {
2579    struct ConfItem *conf = cnode->data;
2580
2581    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2582          (conf->type == OPER_TYPE));
2583
2584    aconf = map_to_conf(conf);
2585    if (aconf->class_ptr != NULL)
2586      return aconf->class_ptr->name;
2587  }
2588
2589  return "default";
2590 }
2591
2592 /* get_client_ping()
2593 *
2594 * inputs       - pointer to client struct
2595 *              - pointer to a variable that receives ping warning time
2596 * output       - ping frequency
2597 * side effects - NONE
2598 */
2599 int
2600 get_client_ping(struct Client *target_p, int *pingwarn)
2601 {
2602  int ping = 0;
2603  dlink_node *cnode = NULL;
2604
2605  if ((cnode = target_p->localClient->confs.head))
2606  {
2607    struct ConfItem *conf = cnode->data;
2608
2609    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2610          (conf->type == OPER_TYPE));
2611
2612    ping = get_conf_ping(conf, pingwarn);
2613    if (ping > 0)
2614      return ping;
2615  }
2616
2617  *pingwarn = 0;
2618  return DEFAULT_PINGFREQUENCY;
2619 }
2620
2621 /* find_class()
2622 *
2623 * inputs       - string name of class
2624 * output       - corresponding Class pointer
2625 * side effects - NONE
2626 */
2627 struct ConfItem *
2628 find_class(const char *classname)
2629 {
2630  struct ConfItem *conf;
2631
2632  if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2633    return conf;
2634
2635  return class_default;
2636 }
2637
2638 /* check_class()
2639 *
2640 * inputs       - NONE
2641 * output       - NONE
2642 * side effects -
2643 */
2644 void
2645 check_class(void)
2646 {
2647  dlink_node *ptr = NULL, *next_ptr = NULL;
2648
2649  DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2650  {
2651    struct ClassItem *aclass = map_to_conf(ptr->data);
2652
2653    if (!aclass->active && !aclass->curr_user_count)
2654    {
2655      destroy_cidr_class(aclass);
2656      delete_conf_item(ptr->data);
2657    }
2658  }
2659 }
2660
2661 /* init_class()
2662 *
2663 * inputs       - NONE
2664 * output       - NONE
2665 * side effects -
2666 */
2667 void
2668 init_class(void)
2669 {
2670  struct ClassItem *aclass;
2671
2672  class_default = make_conf_item(CLASS_TYPE);
2673
2674  aclass = map_to_conf(class_default);
2675  aclass->active = 1;
2676  DupString(class_default->name, "default");
2677  aclass->con_freq  = DEFAULT_CONNECTFREQUENCY;
2678  aclass->ping_freq = DEFAULT_PINGFREQUENCY;
2679  aclass->max_total = MAXIMUM_LINKS_DEFAULT;
2680  aclass->max_sendq = DEFAULT_SENDQ;
2681  aclass->max_recvq = DEFAULT_RECVQ;
2682
2683  client_check_cb = register_callback("check_client", check_client);
2684 }
2685
2686 /* get_sendq()
2687 *
2688 * inputs       - pointer to client
2689 * output       - sendq for this client as found from its class
2690 * side effects - NONE
2691 */
2692 unsigned int
2693 get_sendq(struct Client *client_p)
2694 {
2695  unsigned int sendq = DEFAULT_SENDQ;
2696  dlink_node *cnode;
2697  struct ConfItem *class_conf;
2698  struct ClassItem *aclass;
2699  struct AccessItem *aconf;
2700
2701  assert(!IsMe(client_p));
2702
2703  if ((cnode = client_p->localClient->confs.head))
2704  {
2705    struct ConfItem *conf = cnode->data;
2706
2707    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2708          (conf->type == OPER_TYPE));
2709
2710    aconf = map_to_conf(conf);
2711
2712    if ((class_conf = aconf->class_ptr) == NULL)
2713      return DEFAULT_SENDQ; /* TBV: shouldn't be possible at all */
2714
2715    aclass = map_to_conf(class_conf);
2716    sendq = aclass->max_sendq;
2717    return sendq;
2718  }
2719
2720  /* XXX return a default?
2721   * if here, then there wasn't an attached conf with a sendq
2722   * that is very bad -Dianora
2723   */
2724  return DEFAULT_SENDQ;
2725 }
2726
2727 unsigned int
2728 get_recvq(struct Client *client_p)
2729 {
2730  unsigned int recvq = DEFAULT_RECVQ;
2731  dlink_node *cnode;
2732  struct ConfItem *class_conf;
2733  struct ClassItem *aclass;
2734  struct AccessItem *aconf;
2735
2736  assert(!IsMe(client_p));
2737
2738  if ((cnode = client_p->localClient->confs.head))
2739  {
2740    struct ConfItem *conf = cnode->data;
2741
2742    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2743          (conf->type == OPER_TYPE));
2744
2745    aconf = map_to_conf(conf);
2746
2747    if ((class_conf = aconf->class_ptr) == NULL)
2748      return DEFAULT_RECVQ; /* TBV: shouldn't be possible at all */
2749
2750    aclass = map_to_conf(class_conf);
2751    recvq = aclass->max_recvq;
2752    return recvq;
2753  }
2754
2755  /* XXX return a default?
2756   * if here, then there wasn't an attached conf with a recvq
2757   * that is very bad -Dianora
2758   */
2759  return DEFAULT_RECVQ;
1635   }
1636  
1637   /* conf_add_class_to_conf()
# Line 2766 | Line 1641 | get_recvq(struct Client *client_p)
1641   * side effects - Add a class pointer to a conf
1642   */
1643   void
1644 < conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
1644 > conf_add_class_to_conf(struct MaskItem *conf, const char *class_name)
1645   {
2771  struct AccessItem *aconf = map_to_conf(conf);
2772  struct ClassItem *class = NULL;
2773
1646    if (class_name == NULL)
1647    {
1648 <    aconf->class_ptr = class_default;
1648 >    conf->class = class_default;
1649  
1650 <    if (conf->type == CLIENT_TYPE)
1650 >    if (conf->type == CONF_CLIENT)
1651        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1652 <                           "Warning *** Defaulting to default class for %s@%s",
1653 <                           aconf->user, aconf->host);
1652 >                           "Warning *** Defaulting to default class for %s@%s",
1653 >                           conf->user, conf->host);
1654      else
1655        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1656 <                           "Warning *** Defaulting to default class for %s",
1657 <                           conf->name);
1656 >                           "Warning *** Defaulting to default class for %s",
1657 >                           conf->name);
1658    }
1659    else
1660 <    aconf->class_ptr = find_class(class_name);
1660 >    conf->class = class_find(class_name, 1);
1661  
1662 <  if (aconf->class_ptr)
2791 <    class = map_to_conf(aconf->class_ptr);
2792 <
2793 <  if (aconf->class_ptr == NULL || !class->active)
1662 >  if (conf->class == NULL)
1663    {
1664 <    if (conf->type == CLIENT_TYPE)
1664 >    if (conf->type == CONF_CLIENT)
1665        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1666 <                           "Warning *** Defaulting to default class for %s@%s",
1667 <                           aconf->user, aconf->host);
1666 >                           "Warning *** Defaulting to default class for %s@%s",
1667 >                           conf->user, conf->host);
1668      else
1669        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1670 <                           "Warning *** Defaulting to default class for %s",
1671 <                           conf->name);
1672 <    aconf->class_ptr = class_default;
1670 >                           "Warning *** Defaulting to default class for %s",
1671 >                           conf->name);
1672 >    conf->class = class_default;
1673    }
1674   }
1675  
2807 /* conf_add_server()
2808 *
2809 * inputs       - pointer to config item
2810 *              - pointer to link count already on this conf
2811 * output       - NONE
2812 * side effects - Add a connect block
2813 */
2814 int
2815 conf_add_server(struct ConfItem *conf, const char *class_name)
2816 {
2817  struct AccessItem *aconf = map_to_conf(conf);
2818
2819  conf_add_class_to_conf(conf, class_name);
2820
2821  if (!aconf->host || !conf->name)
2822  {
2823    sendto_realops_flags(UMODE_ALL, L_ALL,  SEND_NOTICE,
2824                         "Bad connect block");
2825    ilog(LOG_TYPE_IRCD, "Bad connect block");
2826    return -1;
2827  }
2828
2829  if (EmptyString(aconf->passwd))
2830  {
2831    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2832                         "Bad connect block, name %s",
2833                         conf->name);
2834    ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
2835    return -1;
2836  }
2837
2838  lookup_confhost(conf);
2839
2840  return 0;
2841 }
2842
1676   /* yyerror()
1677   *
1678   * inputs       - message from parser
# Line 2855 | Line 1688 | yyerror(const char *msg)
1688      return;
1689  
1690    strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1691 <  sendto_realops_flags(UMODE_ALL, L_ALL,  SEND_NOTICE,
1691 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1692 >                       "\"%s\", line %u: %s: %s",
1693 >                       conffilebuf, lineno + 1, msg, newlinebuf);
1694 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1695 >       conffilebuf, lineno + 1, msg, newlinebuf);
1696 > }
1697 >
1698 > void
1699 > conf_error_report(const char *msg)
1700 > {
1701 >  char newlinebuf[IRCD_BUFSIZE];
1702 >
1703 >  strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1704 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1705                         "\"%s\", line %u: %s: %s",
1706                         conffilebuf, lineno + 1, msg, newlinebuf);
1707    ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
# Line 2873 | Line 1719 | yyerror(const char *msg)
1719   * Originally written by Dianora (Diane, db@db.net)
1720   */
1721   time_t
1722 < valid_tkline(const char *p, int minutes)
1722 > valid_tkline(const char *data, const int minutes)
1723   {
1724 +  const unsigned char *p = (const unsigned char *)data;
1725 +  unsigned char tmpch = '\0';
1726    time_t result = 0;
1727  
1728 <  for (; *p; ++p)
1728 >  while ((tmpch = *p++))
1729    {
1730 <    if (!IsDigit(*p))
1730 >    if (!IsDigit(tmpch))
1731        return 0;
1732  
1733      result *= 10;
1734 <    result += ((*p) & 0xF);
1734 >    result += (tmpch & 0xF);
1735    }
1736  
1737    /*
# Line 2899 | Line 1747 | valid_tkline(const char *p, int minutes)
1747     * of this calculation
1748     */
1749    if (!minutes)
1750 <    result = result / (time_t)60;
1750 >    result = result / 60;
1751  
1752    if (result > MAX_TDKLINE_TIME)
1753      result = MAX_TDKLINE_TIME;
1754  
1755 <  result = result * (time_t)60;  /* turn it into seconds */
1755 >  result = result * 60;  /* turn it into seconds */
1756  
1757    return result;
1758   }
1759  
1760 + /* valid_wild_card_simple()
1761 + *
1762 + * inputs       - data to check for sufficient non-wildcard characters
1763 + * outputs      - 1 if valid, else 0
1764 + * side effects - none
1765 + */
1766 + int
1767 + valid_wild_card_simple(const char *data)
1768 + {
1769 +  const unsigned char *p = (const unsigned char *)data;
1770 +  unsigned char tmpch = '\0';
1771 +  int nonwild = 0;
1772 +
1773 +  while ((tmpch = *p++))
1774 +  {
1775 +    if (tmpch == '\\')
1776 +    {
1777 +      ++p;
1778 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1779 +        return 1;
1780 +    }
1781 +    else if (!IsMWildChar(tmpch))
1782 +    {
1783 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1784 +        return 1;
1785 +    }
1786 +  }
1787 +
1788 +  return 0;
1789 + }
1790 +
1791   /* valid_wild_card()
1792   *
1793   * input        - pointer to client
# Line 2920 | Line 1799 | valid_tkline(const char *p, int minutes)
1799   int
1800   valid_wild_card(struct Client *source_p, int warn, int count, ...)
1801   {
2923  char *p;
1802    char tmpch;
1803    int nonwild = 0;
1804    va_list args;
# Line 2941 | Line 1819 | valid_wild_card(struct Client *source_p,
1819  
1820    while (count--)
1821    {
1822 <    p = va_arg(args, char *);
1822 >    const char *p = va_arg(args, const char *);
1823      if (p == NULL)
1824        continue;
1825  
# Line 2997 | Line 1875 | valid_wild_card(struct Client *source_p,
1875   */
1876   int
1877   parse_aline(const char *cmd, struct Client *source_p,
1878 <            int parc, char **parv,
1879 <            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1880 <            char **target_server, char **reason)
1878 >            int parc, char **parv,
1879 >            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1880 >            char **target_server, char **reason)
1881   {
1882    int found_tkline_time=0;
1883    static char def_reason[] = "No Reason";
# Line 3021 | Line 1899 | parse_aline(const char *cmd, struct Clie
1899      else
1900      {
1901        sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
1902 <                 me.name, source_p->name, cmd);
1902 >                 me.name, source_p->name, cmd);
1903        return -1;
1904      }
1905    }
# Line 3056 | Line 1934 | parse_aline(const char *cmd, struct Clie
1934  
1935        if (target_server == NULL)
1936        {
1937 <        sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
1938 <                   me.name, source_p->name, cmd);
1939 <        return -1;
1937 >        sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
1938 >                   me.name, source_p->name, cmd);
1939 >        return -1;
1940        }
1941  
1942        if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
# Line 3070 | Line 1948 | parse_aline(const char *cmd, struct Clie
1948  
1949        if (parc == 0 || EmptyString(*parv))
1950        {
1951 <        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1952 <                   me.name, source_p->name, cmd);
1953 <        return -1;
1951 >        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1952 >                   me.name, source_p->name, cmd);
1953 >        return -1;
1954        }
1955  
1956        *target_server = *parv;
# Line 3085 | Line 1963 | parse_aline(const char *cmd, struct Clie
1963         * caller probably NULL'd it first, but no harm to do it again -db
1964         */
1965        if (target_server != NULL)
1966 <        *target_server = NULL;
1966 >        *target_server = NULL;
1967      }
1968    }
1969  
# Line 3111 | Line 1989 | parse_aline(const char *cmd, struct Clie
1989      {
1990        *reason = *parv;
1991        if (!valid_comment(source_p, *reason, 1))
1992 <        return -1;
1992 >        return -1;
1993      }
1994      else
1995        *reason = def_reason;
# Line 3150 | Line 2028 | find_user_host(struct Client *source_p,
2028      {
2029        *(hostp++) = '\0';                       /* short and squat */
2030        if (*user_host_or_nick)
2031 <        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
2031 >        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
2032        else
2033 <        strcpy(luser, "*");
2033 >        strcpy(luser, "*");
2034 >
2035        if (*hostp)
2036 <        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
2036 >        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
2037        else
2038 <        strcpy(lhost, "*");
2038 >        strcpy(lhost, "*");
2039      }
2040      else
2041      {
2042        luser[0] = '*';             /* no @ found, assume its *@somehost */
2043 <      luser[1] = '\0';    
2043 >      luser[1] = '\0';
2044        strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
2045      }
2046      
# Line 3178 | Line 2057 | find_user_host(struct Client *source_p,
2057      if (IsExemptKline(target_p))
2058      {
2059        if (!IsServer(source_p))
2060 <        sendto_one(source_p,
2061 <                   ":%s NOTICE %s :%s is E-lined",
2062 <                   me.name, source_p->name, target_p->name);
2060 >        sendto_one(source_p,
2061 >                   ":%s NOTICE %s :%s is E-lined",
2062 >                   me.name, source_p->name, target_p->name);
2063        return 0;
2064      }
2065  
# Line 3215 | Line 2094 | find_user_host(struct Client *source_p,
2094   int
2095   valid_comment(struct Client *source_p, char *comment, int warn)
2096   {
3218  if (strchr(comment, '"'))
3219  {
3220    if (warn)
3221      sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3222                 me.name, source_p->name);
3223    return 0;
3224  }
3225
2097    if (strlen(comment) > REASONLEN)
2098      comment[REASONLEN-1] = '\0';
2099  
# Line 3237 | Line 2108 | valid_comment(struct Client *source_p, c
2108   * side effects - none
2109   */
2110   int
2111 < match_conf_password(const char *password, const struct AccessItem *aconf)
2111 > match_conf_password(const char *password, const struct MaskItem *conf)
2112   {
2113    const char *encr = NULL;
2114  
2115 <  if (EmptyString(password) || EmptyString(aconf->passwd))
2115 >  if (EmptyString(password) || EmptyString(conf->passwd))
2116      return 0;
2117  
2118 <  if (aconf->flags & CONF_FLAGS_ENCRYPTED)
2119 <    encr = crypt(password, aconf->passwd);
2118 >  if (conf->flags & CONF_FLAGS_ENCRYPTED)
2119 >    encr = crypt(password, conf->passwd);
2120    else
2121      encr = password;
2122  
2123 <  return !strcmp(encr, aconf->passwd);
2123 >  return !strcmp(encr, conf->passwd);
2124   }
2125  
2126   /*
# Line 3278 | Line 2149 | cluster_a_line(struct Client *source_p,
2149  
2150    DLINK_FOREACH(ptr, cluster_items.head)
2151    {
2152 <    const struct ConfItem *conf = ptr->data;
2152 >    const struct MaskItem *conf = ptr->data;
2153  
2154      if (conf->flags & cluster_type)
2155        sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
2156 <                         "%s %s %s", command, conf->name, buffer);
2156 >                         "%s %s %s", command, conf->name, buffer);
2157    }
2158   }
2159  
# Line 3372 | Line 2243 | split_nuh(struct split_nuh_item *const i
2243      }
2244    }
2245   }
3375
3376 /*
3377 * flags_to_ascii
3378 *
3379 * inputs       - flags is a bitmask
3380 *              - pointer to table of ascii letters corresponding
3381 *                to each bit
3382 *              - flag 1 for convert ToLower if bit missing
3383 *                0 if ignore.
3384 * output       - none
3385 * side effects - string pointed to by p has bitmap chars written to it
3386 */
3387 static void
3388 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3389               int lowerit)
3390 {
3391  unsigned int mask = 1;
3392  int i = 0;
3393
3394  for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3395  {
3396    if (flags & mask)
3397      *p++ = bit_table[i];
3398    else if (lowerit)
3399      *p++ = ToLower(bit_table[i]);
3400  }
3401  *p = '\0';
3402 }
3403
3404 /*
3405 * cidr_limit_reached
3406 *
3407 * inputs       - int flag allowing over_rule of limits
3408 *              - pointer to the ip to be added
3409 *              - pointer to the class
3410 * output       - non zero if limit reached
3411 *                0 if limit not reached
3412 * side effects -
3413 */
3414 static int
3415 cidr_limit_reached(int over_rule,
3416                   struct irc_ssaddr *ip, struct ClassItem *aclass)
3417 {
3418  dlink_node *ptr = NULL;
3419  struct CidrItem *cidr;
3420
3421  if (aclass->number_per_cidr <= 0)
3422    return 0;
3423
3424  if (ip->ss.ss_family == AF_INET)
3425  {
3426    if (aclass->cidr_bitlen_ipv4 <= 0)
3427      return 0;
3428
3429    DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3430    {
3431      cidr = ptr->data;
3432      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3433      {
3434        if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3435          return -1;
3436        cidr->number_on_this_cidr++;
3437        return 0;
3438      }
3439    }
3440    cidr = MyMalloc(sizeof(struct CidrItem));
3441    cidr->number_on_this_cidr = 1;
3442    cidr->mask = *ip;
3443    mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv4);
3444    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3445  }
3446 #ifdef IPV6
3447  else if (aclass->cidr_bitlen_ipv6 > 0)
3448  {
3449    DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3450    {
3451      cidr = ptr->data;
3452      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3453      {
3454        if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3455          return -1;
3456        cidr->number_on_this_cidr++;
3457        return 0;
3458      }
3459    }
3460    cidr = MyMalloc(sizeof(struct CidrItem));
3461    cidr->number_on_this_cidr = 1;
3462    cidr->mask = *ip;
3463    mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv6);
3464    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3465  }
3466 #endif
3467  return 0;
3468 }
3469
3470 /*
3471 * remove_from_cidr_check
3472 *
3473 * inputs       - pointer to the ip to be removed
3474 *              - pointer to the class
3475 * output       - NONE
3476 * side effects -
3477 */
3478 static void
3479 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3480 {
3481  dlink_node *ptr = NULL;
3482  dlink_node *next_ptr = NULL;
3483  struct CidrItem *cidr;
3484
3485  if (aclass->number_per_cidr == 0)
3486    return;
3487
3488  if (ip->ss.ss_family == AF_INET)
3489  {
3490    if (aclass->cidr_bitlen_ipv4 <= 0)
3491      return;
3492
3493    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3494    {
3495      cidr = ptr->data;
3496      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3497      {
3498        cidr->number_on_this_cidr--;
3499        if (cidr->number_on_this_cidr == 0)
3500        {
3501          dlinkDelete(ptr, &aclass->list_ipv4);
3502          MyFree(cidr);
3503          return;
3504        }
3505      }
3506    }
3507  }
3508 #ifdef IPV6
3509  else if (aclass->cidr_bitlen_ipv6 > 0)
3510  {
3511    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3512    {
3513      cidr = ptr->data;
3514      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3515      {
3516        cidr->number_on_this_cidr--;
3517        if (cidr->number_on_this_cidr == 0)
3518        {
3519          dlinkDelete(ptr, &aclass->list_ipv6);
3520          MyFree(cidr);
3521          return;
3522        }
3523      }
3524    }
3525  }
3526 #endif
3527 }
3528
3529 static void
3530 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3531                  dlink_list *old_list, dlink_list *new_list, int changed)
3532 {
3533  dlink_node *ptr;
3534  struct Client *client_p;
3535  struct ConfItem *conf;
3536  struct AccessItem *aconf;
3537
3538  if (!changed)
3539  {
3540    *new_list = *old_list;
3541    old_list->head = old_list->tail = NULL;
3542    old_list->length = 0;
3543    return;
3544  }
3545
3546  DLINK_FOREACH(ptr, local_client_list.head)
3547  {
3548    client_p = ptr->data;
3549    if (client_p->localClient->aftype != aftype)
3550      continue;
3551    if (dlink_list_length(&client_p->localClient->confs) == 0)
3552      continue;
3553
3554    conf = client_p->localClient->confs.tail->data;
3555    if (conf->type == CLIENT_TYPE)
3556    {
3557      aconf = map_to_conf(conf);
3558      if (aconf->class_ptr == oldcl)
3559        cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3560    }
3561  }
3562 }
3563
3564 /*
3565 * rebuild_cidr_class
3566 *
3567 * inputs       - pointer to old conf
3568 *              - pointer to new_class
3569 * output       - none
3570 * side effects - rebuilds the class link list of cidr blocks
3571 */
3572 void
3573 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3574 {
3575  struct ClassItem *old_class = map_to_conf(conf);
3576
3577  if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
3578  {
3579    if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
3580      rebuild_cidr_list(AF_INET, conf, new_class,
3581                        &old_class->list_ipv4, &new_class->list_ipv4,
3582                        old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
3583
3584 #ifdef IPV6
3585    if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
3586      rebuild_cidr_list(AF_INET6, conf, new_class,
3587                        &old_class->list_ipv6, &new_class->list_ipv6,
3588                        old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
3589 #endif
3590  }
3591
3592  destroy_cidr_class(old_class);
3593 }
3594
3595 /*
3596 * destroy_cidr_list
3597 *
3598 * inputs       - pointer to class dlink list of cidr blocks
3599 * output       - none
3600 * side effects - completely destroys the class link list of cidr blocks
3601 */
3602 static void
3603 destroy_cidr_list(dlink_list *list)
3604 {
3605  dlink_node *ptr = NULL, *next_ptr = NULL;
3606
3607  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3608  {
3609    dlinkDelete(ptr, list);
3610    MyFree(ptr->data);
3611  }
3612 }
3613
3614 /*
3615 * destroy_cidr_class
3616 *
3617 * inputs       - pointer to class
3618 * output       - none
3619 * side effects - completely destroys the class link list of cidr blocks
3620 */
3621 static void
3622 destroy_cidr_class(struct ClassItem *aclass)
3623 {
3624  destroy_cidr_list(&aclass->list_ipv4);
3625  destroy_cidr_list(&aclass->list_ipv6);
3626 }

Diff Legend

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