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

Comparing:
ircd-hybrid-8/src/conf.c (file contents), Revision 1381 by michael, Tue May 1 08:21:27 2012 UTC vs.
ircd-hybrid/trunk/src/conf.c (file contents), Revision 2138 by michael, Wed May 29 21:14:02 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  
55 struct Callback *client_check_cb = NULL;
57   struct config_server_hide ConfigServerHide;
58  
59   /* general conf items link list root, other than k lines etc. */
60   dlink_list service_items = { NULL, NULL, 0 };
61   dlink_list server_items  = { NULL, NULL, 0 };
62   dlink_list cluster_items = { NULL, NULL, 0 };
62 dlink_list hub_items     = { NULL, NULL, 0 };
63 dlink_list leaf_items    = { NULL, NULL, 0 };
63   dlink_list oconf_items   = { NULL, NULL, 0 };
64   dlink_list uconf_items   = { NULL, NULL, 0 };
65   dlink_list xconf_items   = { NULL, NULL, 0 };
67 dlink_list rxconf_items  = { NULL, NULL, 0 };
68 dlink_list rkconf_items  = { NULL, NULL, 0 };
66   dlink_list nresv_items   = { NULL, NULL, 0 };
70 dlink_list class_items   = { NULL, NULL, 0 };
71 dlink_list gdeny_items   = { NULL, NULL, 0 };
72
73 dlink_list temporary_xlines  = { NULL, NULL, 0 };
67   dlink_list temporary_resv = { NULL, NULL, 0 };
68  
69   extern unsigned int lineno;
# Line 83 | Line 76 | struct conf_parser_context conf_parser_c
76   /* internally defined functions */
77   static void read_conf(FILE *);
78   static void clear_out_old_conf(void);
86 static void flush_deleted_I_P(void);
79   static void expire_tklines(dlink_list *);
80   static void garbage_collect_ip_entries(void);
81   static int hash_ip(struct irc_ssaddr *);
82 < static int verify_access(struct Client *, const char *);
83 < static int attach_iline(struct Client *, struct ConfItem *);
82 > static int verify_access(struct Client *);
83 > static int attach_iline(struct Client *, struct MaskItem *);
84   static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
85 < static void parse_conf_file(int, int);
94 < static dlink_list *map_to_list(ConfType);
95 < static struct AccessItem *find_regexp_kline(const char *[]);
85 > static dlink_list *map_to_list(enum maskitem_type);
86   static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
87  
98 /*
99 * bit_len
100 */
101 static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
102 static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
103 static void destroy_cidr_class(struct ClassItem *);
104
105 static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
106
107 /* address of default class conf */
108 static struct ConfItem *class_default;
88  
89   /* usually, with hash tables, you use a prime number...
90   * but in this case I am dealing with ip addresses,
# Line 116 | Line 95 | static struct ConfItem *class_default;
95   struct ip_entry
96   {
97    struct irc_ssaddr ip;
98 <  int count;
98 >  unsigned int count;
99    time_t last_attempt;
100    struct ip_entry *next;
101   };
102  
103   static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
104 < static BlockHeap *ip_entry_heap = NULL;
104 > static mp_pool_t *ip_entry_pool = NULL;
105   static int ip_entries_count = 0;
106  
107  
129 void *
130 map_to_conf(struct ConfItem *aconf)
131 {
132  void *conf;
133  conf = (void *)((uintptr_t)aconf +
134                  (uintptr_t)sizeof(struct ConfItem));
135  return(conf);
136 }
137
138 struct ConfItem *
139 unmap_conf_item(void *aconf)
140 {
141  struct ConfItem *conf;
142
143  conf = (struct ConfItem *)((uintptr_t)aconf -
144                             (uintptr_t)sizeof(struct ConfItem));
145  return(conf);
146 }
147
108   /* conf_dns_callback()
109   *
110 < * inputs       - pointer to struct AccessItem
110 > * inputs       - pointer to struct MaskItem
111   *              - pointer to DNSReply reply
112   * output       - none
113   * side effects - called when resolver query finishes
# Line 158 | Line 118 | unmap_conf_item(void *aconf)
118   static void
119   conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
120   {
121 <  struct AccessItem *aconf = vptr;
121 >  struct MaskItem *conf = vptr;
122  
123 <  aconf->dns_pending = 0;
123 >  conf->dns_pending = 0;
124  
125    if (addr != NULL)
126 <    memcpy(&aconf->ipnum, addr, sizeof(aconf->ipnum));
126 >    memcpy(&conf->addr, addr, sizeof(conf->addr));
127    else
128 <    aconf->dns_failed = 1;
128 >    conf->dns_failed = 1;
129   }
130  
131   /* conf_dns_lookup()
# Line 175 | Line 135 | conf_dns_callback(void *vptr, const stru
135   * allocate a dns_query and start ns lookup.
136   */
137   static void
138 < conf_dns_lookup(struct AccessItem *aconf)
138 > conf_dns_lookup(struct MaskItem *conf)
139   {
140 <  if (!aconf->dns_pending)
140 >  if (!conf->dns_pending)
141    {
142 <    aconf->dns_pending = 1;
143 <    gethost_byname(conf_dns_callback, aconf, aconf->host);
142 >    conf->dns_pending = 1;
143 >    gethost_byname(conf_dns_callback, conf, conf->host);
144    }
145   }
146  
147 < /* make_conf_item()
148 < *
189 < * inputs       - type of item
190 < * output       - pointer to new conf entry
191 < * side effects - none
192 < */
193 < struct ConfItem *
194 < make_conf_item(ConfType type)
147 > struct MaskItem *
148 > conf_make(enum maskitem_type type)
149   {
150 <  struct ConfItem *conf = NULL;
151 <  struct AccessItem *aconf = NULL;
198 <  struct ClassItem *aclass = NULL;
199 <  int status = 0;
200 <
201 <  switch (type)
202 <  {
203 <  case DLINE_TYPE:
204 <  case EXEMPTDLINE_TYPE:
205 <  case GLINE_TYPE:
206 <  case KLINE_TYPE:
207 <  case CLIENT_TYPE:
208 <  case OPER_TYPE:
209 <  case SERVER_TYPE:
210 <    conf = MyMalloc(sizeof(struct ConfItem) +
211 <                    sizeof(struct AccessItem));
212 <    aconf = map_to_conf(conf);
213 <    aconf->aftype = AF_INET;
214 <
215 <    /* Yes, sigh. switch on type again */
216 <    switch (type)
217 <    {
218 <    case EXEMPTDLINE_TYPE:
219 <      status = CONF_EXEMPTDLINE;
220 <      break;
221 <
222 <    case DLINE_TYPE:
223 <      status = CONF_DLINE;
224 <      break;
150 >  struct MaskItem *conf = MyMalloc(sizeof(*conf));
151 >  dlink_list *list = NULL;
152  
153 <    case KLINE_TYPE:
154 <      status = CONF_KLINE;
155 <      break;
229 <
230 <    case GLINE_TYPE:
231 <      status = CONF_GLINE;
232 <      break;
233 <
234 <    case CLIENT_TYPE:
235 <      status = CONF_CLIENT;
236 <      break;
237 <
238 <    case OPER_TYPE:
239 <      status = CONF_OPERATOR;
240 <      dlinkAdd(conf, &conf->node, &oconf_items);
241 <      break;
242 <
243 <    case SERVER_TYPE:
244 <      status = CONF_SERVER;
245 <      dlinkAdd(conf, &conf->node, &server_items);
246 <      break;
247 <
248 <    default:
249 <      break;
250 <    }
251 <    aconf->status = status;
252 <    break;
253 <
254 <  case LEAF_TYPE:
255 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
256 <                                       sizeof(struct MatchItem));
257 <    dlinkAdd(conf, &conf->node, &leaf_items);
258 <    break;
259 <
260 <  case HUB_TYPE:
261 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
262 <                                       sizeof(struct MatchItem));
263 <    dlinkAdd(conf, &conf->node, &hub_items);
264 <    break;
265 <
266 <  case ULINE_TYPE:
267 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
268 <                                       sizeof(struct MatchItem));
269 <    dlinkAdd(conf, &conf->node, &uconf_items);
270 <    break;
271 <
272 <  case GDENY_TYPE:
273 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
274 <                                       sizeof(struct AccessItem));
275 <    dlinkAdd(conf, &conf->node, &gdeny_items);
276 <    break;
277 <
278 <  case XLINE_TYPE:
279 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
280 <                                       sizeof(struct MatchItem));
281 <    dlinkAdd(conf, &conf->node, &xconf_items);
282 <    break;
283 < #ifdef HAVE_LIBPCRE
284 <  case RXLINE_TYPE:
285 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
286 <                                       sizeof(struct MatchItem));
287 <    dlinkAdd(conf, &conf->node, &rxconf_items);
288 <    break;
289 <
290 <  case RKLINE_TYPE:
291 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
292 <                                       sizeof(struct AccessItem));
293 <    aconf = map_to_conf(conf);
294 <    aconf->status = CONF_KLINE;
295 <    dlinkAdd(conf, &conf->node, &rkconf_items);
296 <    break;
297 < #endif
298 <  case CLUSTER_TYPE:
299 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
300 <    dlinkAdd(conf, &conf->node, &cluster_items);
301 <    break;
302 <
303 <  case CRESV_TYPE:
304 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
305 <                                       sizeof(struct ResvChannel));
306 <    break;
307 <
308 <  case NRESV_TYPE:
309 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
310 <                                       sizeof(struct MatchItem));
311 <    dlinkAdd(conf, &conf->node, &nresv_items);
312 <    break;
313 <
314 <  case SERVICE_TYPE:
315 <    status = CONF_SERVICE;
316 <    conf = MyMalloc(sizeof(struct ConfItem));
317 <    dlinkAdd(conf, &conf->node, &service_items);
318 <    break;
319 <
320 <  case CLASS_TYPE:
321 <    conf = MyMalloc(sizeof(struct ConfItem) +
322 <                           sizeof(struct ClassItem));
323 <    dlinkAdd(conf, &conf->node, &class_items);
324 <
325 <    aclass = map_to_conf(conf);
326 <    aclass->active = 1;
327 <    aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
328 <    aclass->ping_freq = DEFAULT_PINGFREQUENCY;
329 <    aclass->max_total = MAXIMUM_LINKS_DEFAULT;
330 <    aclass->max_sendq = DEFAULT_SENDQ;
331 <
332 <    break;
333 <
334 <  default:
335 <    conf = NULL;
336 <    break;
337 <  }
338 <
339 <  /* XXX Yes, this will core if default is hit. I want it to for now - db */
340 <  conf->type = type;
153 >  conf->type   = type;
154 >  conf->active = 1;
155 >  conf->aftype = AF_INET;
156  
157 +  if ((list = map_to_list(type)))
158 +    dlinkAdd(conf, &conf->node, list);
159    return conf;
160   }
161  
162   void
163 < delete_conf_item(struct ConfItem *conf)
163 > conf_free(struct MaskItem *conf)
164   {
165 <  dlink_node *m = NULL;
166 <  struct MatchItem *match_item;
167 <  struct AccessItem *aconf;
168 <  ConfType type = conf->type;
165 >  dlink_node *ptr = NULL, *ptr_next = NULL;
166 >  dlink_list *list = NULL;
167 >
168 >  if (conf->node.next)
169 >    if ((list = map_to_list(conf->type)))
170 >      dlinkDelete(&conf->node, list);
171  
172    MyFree(conf->name);
354  conf->name = NULL;
173  
174 <  switch(type)
175 <  {
176 <  case DLINE_TYPE:
177 <  case EXEMPTDLINE_TYPE:
178 <  case GLINE_TYPE:
179 <  case KLINE_TYPE:
180 <  case CLIENT_TYPE:
181 <  case OPER_TYPE:
182 <  case SERVER_TYPE:
183 <    aconf = map_to_conf(conf);
184 <
185 <    if (aconf->dns_pending)
186 <      delete_resolver_queries(aconf);
187 <    if (aconf->passwd != NULL)
370 <      memset(aconf->passwd, 0, strlen(aconf->passwd));
371 <    if (aconf->spasswd != NULL)
372 <      memset(aconf->spasswd, 0, strlen(aconf->spasswd));
373 <    aconf->class_ptr = NULL;
374 <
375 <    MyFree(aconf->passwd);
376 <    MyFree(aconf->spasswd);
377 <    MyFree(aconf->reason);
378 <    MyFree(aconf->oper_reason);
379 <    MyFree(aconf->user);
380 <    MyFree(aconf->host);
381 <    MyFree(aconf->cipher_list);
174 >  if (conf->dns_pending)
175 >    delete_resolver_queries(conf);
176 >  if (conf->passwd != NULL)
177 >    memset(conf->passwd, 0, strlen(conf->passwd));
178 >  if (conf->spasswd != NULL)
179 >    memset(conf->spasswd, 0, strlen(conf->spasswd));
180 >
181 >  conf->class = NULL;
182 >
183 >  MyFree(conf->passwd);
184 >  MyFree(conf->spasswd);
185 >  MyFree(conf->reason);
186 >  MyFree(conf->user);
187 >  MyFree(conf->host);
188   #ifdef HAVE_LIBCRYPTO
189 <    if (aconf->rsa_public_key)
384 <      RSA_free(aconf->rsa_public_key);
385 <    MyFree(aconf->rsa_public_key_file);
386 < #endif
189 >  MyFree(conf->cipher_list);
190  
191 <    /* Yes, sigh. switch on type again */
192 <    switch(type)
390 <    {
391 <    case EXEMPTDLINE_TYPE:
392 <    case DLINE_TYPE:
393 <    case GLINE_TYPE:
394 <    case KLINE_TYPE:
395 <    case CLIENT_TYPE:
396 <      MyFree(conf);
397 <      break;
398 <
399 <    case OPER_TYPE:
400 <      aconf = map_to_conf(conf);
401 <      if (!IsConfIllegal(aconf))
402 <        dlinkDelete(&conf->node, &oconf_items);
403 <      MyFree(conf);
404 <      break;
405 <
406 <    case SERVER_TYPE:
407 <      aconf = map_to_conf(conf);
408 <      if (!IsConfIllegal(aconf))
409 <        dlinkDelete(&conf->node, &server_items);
410 <      MyFree(conf);
411 <      break;
412 <
413 <    default:
414 <      break;
415 <    }
416 <    break;
417 <
418 <  case HUB_TYPE:
419 <    match_item = map_to_conf(conf);
420 <    MyFree(match_item->user);
421 <    MyFree(match_item->host);
422 <    MyFree(match_item->reason);
423 <    MyFree(match_item->oper_reason);
424 <    /* If marked illegal, its already been pulled off of the hub_items list */
425 <    if (!match_item->illegal)
426 <      dlinkDelete(&conf->node, &hub_items);
427 <    MyFree(conf);
428 <    break;
429 <
430 <  case LEAF_TYPE:
431 <    match_item = map_to_conf(conf);
432 <    MyFree(match_item->user);
433 <    MyFree(match_item->host);
434 <    MyFree(match_item->reason);
435 <    MyFree(match_item->oper_reason);
436 <    /* If marked illegal, its already been pulled off of the leaf_items list */
437 <    if (!match_item->illegal)
438 <      dlinkDelete(&conf->node, &leaf_items);
439 <    MyFree(conf);
440 <    break;
441 <
442 <  case ULINE_TYPE:
443 <    match_item = map_to_conf(conf);
444 <    MyFree(match_item->user);
445 <    MyFree(match_item->host);
446 <    MyFree(match_item->reason);
447 <    MyFree(match_item->oper_reason);
448 <    dlinkDelete(&conf->node, &uconf_items);
449 <    MyFree(conf);
450 <    break;
451 <
452 <  case XLINE_TYPE:
453 <    match_item = map_to_conf(conf);
454 <    MyFree(match_item->user);
455 <    MyFree(match_item->host);
456 <    MyFree(match_item->reason);
457 <    MyFree(match_item->oper_reason);
458 <    dlinkDelete(&conf->node, &xconf_items);
459 <    MyFree(conf);
460 <    break;
461 < #ifdef HAVE_LIBPCRE
462 <  case RKLINE_TYPE:
463 <    aconf = map_to_conf(conf);
464 <    MyFree(aconf->regexuser);
465 <    MyFree(aconf->regexhost);
466 <    MyFree(aconf->user);
467 <    MyFree(aconf->host);
468 <    MyFree(aconf->reason);
469 <    MyFree(aconf->oper_reason);
470 <    dlinkDelete(&conf->node, &rkconf_items);
471 <    MyFree(conf);
472 <    break;
473 <
474 <  case RXLINE_TYPE:
475 <    MyFree(conf->regexpname);
476 <    match_item = map_to_conf(conf);
477 <    MyFree(match_item->user);
478 <    MyFree(match_item->host);
479 <    MyFree(match_item->reason);
480 <    MyFree(match_item->oper_reason);
481 <    dlinkDelete(&conf->node, &rxconf_items);
482 <    MyFree(conf);
483 <    break;
191 >  if (conf->rsa_public_key)
192 >    RSA_free(conf->rsa_public_key);
193   #endif
194 <  case NRESV_TYPE:
195 <    match_item = map_to_conf(conf);
196 <    MyFree(match_item->user);
197 <    MyFree(match_item->host);
489 <    MyFree(match_item->reason);
490 <    MyFree(match_item->oper_reason);
491 <    dlinkDelete(&conf->node, &nresv_items);
492 <
493 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
494 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
495 <        free_dlink_node(m);
496 <
497 <    MyFree(conf);
498 <    break;
499 <
500 <  case GDENY_TYPE:
501 <    aconf = map_to_conf(conf);
502 <    MyFree(aconf->user);
503 <    MyFree(aconf->host);
504 <    dlinkDelete(&conf->node, &gdeny_items);
505 <    MyFree(conf);
506 <    break;
507 <
508 <  case CLUSTER_TYPE:
509 <    dlinkDelete(&conf->node, &cluster_items);
510 <    MyFree(conf);
511 <    break;
512 <
513 <  case CRESV_TYPE:
514 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
515 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
516 <        free_dlink_node(m);
517 <
518 <    MyFree(conf);
519 <    break;
520 <
521 <  case CLASS_TYPE:
522 <    dlinkDelete(&conf->node, &class_items);
523 <    MyFree(conf);
524 <    break;
525 <
526 <  case SERVICE_TYPE:
527 <    dlinkDelete(&conf->node, &service_items);
528 <    MyFree(conf);
529 <    break;
530 <
531 <  default:
532 <    break;
194 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->hub_list.head)
195 >  {
196 >    MyFree(ptr->data);
197 >    free_dlink_node(ptr);
198    }
534 }
199  
200 < /* free_access_item()
537 < *
538 < * inputs       - pointer to conf to free
539 < * output       - none
540 < * side effects - crucial password fields are zeroed, conf is freed
541 < */
542 < void
543 < free_access_item(struct AccessItem *aconf)
544 < {
545 <  struct ConfItem *conf;
546 <
547 <  if (aconf == NULL)
548 <    return;
549 <  conf = unmap_conf_item(aconf);
550 <  delete_conf_item(conf);
551 < }
552 <
553 < static const unsigned int shared_bit_table[] =
554 <  { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
555 <
556 < /* report_confitem_types()
557 < *
558 < * inputs       - pointer to client requesting confitem report
559 < *              - ConfType to report
560 < * output       - none
561 < * side effects -
562 < */
563 < void
564 < report_confitem_types(struct Client *source_p, ConfType type)
565 < {
566 <  dlink_node *ptr = NULL;
567 <  struct ConfItem *conf = NULL;
568 <  struct AccessItem *aconf = NULL;
569 <  struct MatchItem *matchitem = NULL;
570 <  struct ClassItem *classitem = NULL;
571 <  char buf[12];
572 <  char *p = NULL;
573 <
574 <  switch (type)
200 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->leaf_list.head)
201    {
202 <  case GDENY_TYPE:
203 <    DLINK_FOREACH(ptr, gdeny_items.head)
204 <    {
579 <      conf = ptr->data;
580 <      aconf = map_to_conf(conf);
581 <
582 <      p = buf;
583 <
584 <      if (aconf->flags & GDENY_BLOCK)
585 <        *p++ = 'B';
586 <      else
587 <        *p++ = 'b';
588 <
589 <      if (aconf->flags & GDENY_REJECT)
590 <        *p++ = 'R';
591 <      else
592 <        *p++ = 'r';
593 <
594 <      *p = '\0';
595 <
596 <      sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
597 <                 me.name, RPL_STATSDEBUG, source_p->name,
598 <                 aconf->user, aconf->host, conf->name, buf);
599 <    }
600 <    break;
601 <
602 <  case XLINE_TYPE:
603 <    DLINK_FOREACH(ptr, xconf_items.head)
604 <    {
605 <      conf = ptr->data;
606 <      matchitem = map_to_conf(conf);
607 <
608 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
609 <                 me.name, source_p->name,
610 <                 matchitem->hold ? "x": "X", matchitem->count,
611 <                 conf->name, matchitem->reason);
612 <    }
613 <    break;
614 <
615 < #ifdef HAVE_LIBPCRE
616 <  case RXLINE_TYPE:
617 <    DLINK_FOREACH(ptr, rxconf_items.head)
618 <    {
619 <      conf = ptr->data;
620 <      matchitem = map_to_conf(conf);
621 <
622 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
623 <                 me.name, source_p->name,
624 <                 "XR", matchitem->count,
625 <                 conf->name, matchitem->reason);
626 <    }
627 <    break;
628 <
629 <  case RKLINE_TYPE:
630 <    DLINK_FOREACH(ptr, rkconf_items.head)
631 <    {
632 <      aconf = map_to_conf((conf = ptr->data));
633 <
634 <      sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
635 <                 source_p->name, "KR", aconf->host, aconf->user,
636 <                 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
637 <    }
638 <    break;
639 < #endif
640 <
641 <  case ULINE_TYPE:
642 <    DLINK_FOREACH(ptr, uconf_items.head)
643 <    {
644 <      conf = ptr->data;
645 <      matchitem = map_to_conf(conf);
646 <
647 <      p = buf;
648 <
649 <      /* some of these are redundant for the sake of
650 <       * consistency with cluster{} flags
651 <       */
652 <      *p++ = 'c';
653 <      flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
654 <
655 <      sendto_one(source_p, form_str(RPL_STATSULINE),
656 <                 me.name, source_p->name, conf->name,
657 <                 matchitem->user?matchitem->user: "*",
658 <                 matchitem->host?matchitem->host: "*", buf);
659 <    }
660 <
661 <    DLINK_FOREACH(ptr, cluster_items.head)
662 <    {
663 <      conf = ptr->data;
664 <
665 <      p = buf;
666 <
667 <      *p++ = 'C';
668 <      flags_to_ascii(conf->flags, shared_bit_table, p, 0);
669 <
670 <      sendto_one(source_p, form_str(RPL_STATSULINE),
671 <                 me.name, source_p->name, conf->name,
672 <                 "*", "*", buf);
673 <    }
674 <
675 <    break;
676 <
677 <  case OPER_TYPE:
678 <    DLINK_FOREACH(ptr, oconf_items.head)
679 <    {
680 <      conf = ptr->data;
681 <      aconf = map_to_conf(conf);
682 <
683 <      /* Don't allow non opers to see oper privs */
684 <      if (HasUMode(source_p, UMODE_OPER))
685 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
686 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
687 <                   conf->name, oper_privs_as_string(aconf->port),
688 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
689 <      else
690 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
691 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
692 <                   conf->name, "0",
693 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
694 <    }
695 <    break;
696 <
697 <  case CLASS_TYPE:
698 <    DLINK_FOREACH(ptr, class_items.head)
699 <    {
700 <      conf = ptr->data;
701 <      classitem = map_to_conf(conf);
702 <      sendto_one(source_p, form_str(RPL_STATSYLINE),
703 <                 me.name, source_p->name, 'Y',
704 <                 conf->name, classitem->ping_freq,
705 <                 classitem->con_freq,
706 <                 classitem->max_total, classitem->max_sendq,
707 <                 classitem->curr_user_count,
708 <                 classitem->active ? "active" : "disabled");
709 <    }
710 <    break;
711 <
712 <  case CONF_TYPE:
713 <  case CLIENT_TYPE:
714 <    break;
715 <
716 <  case SERVICE_TYPE:
717 <    DLINK_FOREACH(ptr, service_items.head)
718 <    {
719 <      conf = ptr->data;
720 <      sendto_one(source_p, form_str(RPL_STATSSERVICE),
721 <                 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
722 <    }
723 <    break;
724 <
725 <  case SERVER_TYPE:
726 <    DLINK_FOREACH(ptr, server_items.head)
727 <    {
728 <      p = buf;
729 <
730 <      conf = ptr->data;
731 <      aconf = map_to_conf(conf);
732 <
733 <      buf[0] = '\0';
734 <
735 <      if (IsConfAllowAutoConn(aconf))
736 <        *p++ = 'A';
737 <      if (IsConfSSL(aconf))
738 <        *p++ = 'S';
739 <      if (IsConfTopicBurst(aconf))
740 <        *p++ = 'T';
741 <      if (buf[0] == '\0')
742 <        *p++ = '*';
743 <
744 <      *p = '\0';
745 <
746 <      /*
747 <       * Allow admins to see actual ips unless hide_server_ips is enabled
748 <       */
749 <      if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
750 <        sendto_one(source_p, form_str(RPL_STATSCLINE),
751 <                   me.name, source_p->name, 'C', aconf->host,
752 <                   buf, conf->name, aconf->port,
753 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
754 <        else
755 <          sendto_one(source_p, form_str(RPL_STATSCLINE),
756 <                     me.name, source_p->name, 'C',
757 <                     "*@127.0.0.1", buf, conf->name, aconf->port,
758 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
759 <    }
760 <    break;
761 <
762 <  case HUB_TYPE:
763 <    DLINK_FOREACH(ptr, hub_items.head)
764 <    {
765 <      conf = ptr->data;
766 <      matchitem = map_to_conf(conf);
767 <      sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
768 <                 source_p->name, 'H', matchitem->host, conf->name, 0, "*");
769 <    }
770 <    break;
202 >    MyFree(ptr->data);
203 >    free_dlink_node(ptr);
204 >  }
205  
206 <  case LEAF_TYPE:
207 <    DLINK_FOREACH(ptr, leaf_items.head)
208 <    {
775 <      conf = ptr->data;
776 <      matchitem = map_to_conf(conf);
777 <      sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
778 <                 source_p->name, 'L', matchitem->host, conf->name, 0, "*");
779 <    }
780 <    break;
206 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->exempt_list.head)
207 >  {
208 >    struct exempt *exptr = ptr->data;
209  
210 <  case GLINE_TYPE:
211 <  case KLINE_TYPE:
212 <  case DLINE_TYPE:
213 <  case EXEMPTDLINE_TYPE:
786 <  case CRESV_TYPE:
787 <  case NRESV_TYPE:
788 <  case CLUSTER_TYPE:
789 <  default:
790 <    break;
210 >    MyFree(exptr->name);
211 >    MyFree(exptr->user);
212 >    MyFree(exptr->host);
213 >    MyFree(exptr);
214    }
215 +
216 +  MyFree(conf);
217   }
218  
219   /* check_client()
# Line 804 | Line 229 | report_confitem_types(struct Client *sou
229   *                Look for conf lines which have the same
230   *                status as the flags passed.
231   */
232 < static void *
233 < check_client(va_list args)
232 > int
233 > check_client(struct Client *source_p)
234   {
810  struct Client *source_p = va_arg(args, struct Client *);
811  const char *username = va_arg(args, const char *);
235    int i;
236  
237 <  /* I'm already in big trouble if source_p->localClient is NULL -db */
815 <  if ((i = verify_access(source_p, username)))
237 >  if ((i = verify_access(source_p)))
238      ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
239           source_p->name, source_p->sockhost);
240  
241    switch (i)
242    {
243      case TOO_MANY:
244 <      sendto_realops_flags(UMODE_FULL, L_ALL,
244 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
245                             "Too many on IP for %s (%s).",
246                             get_client_name(source_p, SHOW_IP),
247                             source_p->sockhost);
# Line 830 | Line 252 | check_client(va_list args)
252        break;
253  
254      case I_LINE_FULL:
255 <      sendto_realops_flags(UMODE_FULL, L_ALL,
256 <                           "I-line is full for %s (%s).",
255 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
256 >                           "auth{} block is full for %s (%s).",
257                             get_client_name(source_p, SHOW_IP),
258                             source_p->sockhost);
259        ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
# Line 845 | Line 267 | check_client(va_list args)
267        ++ServerStats.is_ref;
268        /* jdc - lists server name & port connections are on */
269        /*       a purely cosmetical change */
270 <      sendto_realops_flags(UMODE_UNAUTH, L_ALL,
270 >      sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
271                             "Unauthorized client connection from %s [%s] on [%s/%u].",
272                             get_client_name(source_p, SHOW_IP),
273                             source_p->sockhost,
# Line 857 | Line 279 | check_client(va_list args)
279            source_p->localClient->listener->name,
280            source_p->localClient->listener->port);
281  
282 <      /* XXX It is prolematical whether it is better to use the
861 <       * capture reject code here or rely on the connecting too fast code.
862 <       * - Dianora
863 <       */
864 <      if (REJECT_HOLD_TIME > 0)
865 <      {
866 <        sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
867 <                   me.name, source_p->name);
868 <        source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
869 <        SetCaptured(source_p);
870 <      }
871 <      else
872 <        exit_client(source_p, &me, "You are not authorized to use this server");
282 >      exit_client(source_p, &me, "You are not authorized to use this server");
283        break;
284  
285     case BANNED_CLIENT:
286 <     /*
877 <      * Don't exit them immediately, play with them a bit.
878 <      * - Dianora
879 <      */
880 <     if (REJECT_HOLD_TIME > 0)
881 <     {
882 <       source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
883 <       SetCaptured(source_p);
884 <     }
885 <     else
886 <       exit_client(source_p, &me, "Banned");
286 >     exit_client(source_p, &me, "Banned");
287       ++ServerStats.is_ref;
288       break;
289  
# Line 892 | Line 292 | check_client(va_list args)
292       break;
293    }
294  
295 <  return (i < 0 ? NULL : source_p);
295 >  return (i < 0 ? 0 : 1);
296   }
297  
298   /* verify_access()
299   *
300   * inputs       - pointer to client to verify
901 *              - pointer to proposed username
301   * output       - 0 if success -'ve if not
302   * side effect  - find the first (best) I line to attach.
303   */
304   static int
305 < verify_access(struct Client *client_p, const char *username)
305 > verify_access(struct Client *client_p)
306   {
307 <  struct AccessItem *aconf = NULL, *rkconf = NULL;
909 <  struct ConfItem *conf = NULL;
307 >  struct MaskItem *conf = NULL;
308    char non_ident[USERLEN + 1] = { '~', '\0' };
911  const char *uhi[3];
309  
310    if (IsGotId(client_p))
311    {
312 <    aconf = find_address_conf(client_p->host, client_p->username,
312 >    conf = find_address_conf(client_p->host, client_p->username,
313                               &client_p->localClient->ip,
314                               client_p->localClient->aftype,
315                               client_p->localClient->passwd);
316    }
317    else
318    {
319 <    strlcpy(non_ident+1, username, sizeof(non_ident)-1);
320 <    aconf = find_address_conf(client_p->host,non_ident,
319 >    strlcpy(non_ident+1, client_p->username, sizeof(non_ident)-1);
320 >    conf = find_address_conf(client_p->host,non_ident,
321                               &client_p->localClient->ip,
322                               client_p->localClient->aftype,
323                               client_p->localClient->passwd);
324    }
325  
326 <  uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
930 <  uhi[1] = client_p->host;
931 <  uhi[2] = client_p->sockhost;
932 <
933 <  rkconf = find_regexp_kline(uhi);
934 <
935 <  if (aconf != NULL)
326 >  if (conf != NULL)
327    {
328 <    if (IsConfClient(aconf) && !rkconf)
328 >    if (IsConfClient(conf))
329      {
330 <      conf = unmap_conf_item(aconf);
940 <
941 <      if (IsConfRedir(aconf))
330 >      if (IsConfRedir(conf))
331        {
332          sendto_one(client_p, form_str(RPL_REDIR),
333                     me.name, client_p->name,
334                     conf->name ? conf->name : "",
335 <                   aconf->port);
335 >                   conf->port);
336          return(NOT_AUTHORIZED);
337        }
338  
339 <      if (IsConfDoIdentd(aconf))
339 >      if (IsConfDoIdentd(conf))
340          SetNeedId(client_p);
341  
342        /* Thanks for spoof idea amm */
343 <      if (IsConfDoSpoofIp(aconf))
343 >      if (IsConfDoSpoofIp(conf))
344        {
345 <        conf = unmap_conf_item(aconf);
346 <
347 <        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
959 <          sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
345 >        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(conf))
346 >          sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
347 >                               "%s spoofing: %s as %s",
348                                 client_p->name, client_p->host, conf->name);
349          strlcpy(client_p->host, conf->name, sizeof(client_p->host));
350 <        SetIPSpoof(client_p);
350 >        AddFlag(client_p, FLAGS_IP_SPOOFING | FLAGS_AUTH_SPOOF);
351        }
352  
353        return(attach_iline(client_p, conf));
354      }
355 <    else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
355 >    else if (IsConfKill(conf) || (ConfigFileEntry.glines && IsConfGline(conf)))
356      {
357 <      /* XXX */
970 <      aconf = rkconf ? rkconf : aconf;
971 <      if (IsConfGline(aconf))
357 >      if (IsConfGline(conf))
358          sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
359                     client_p->name);
360 <      if (ConfigFileEntry.kline_with_reason)
361 <        sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
976 <                  me.name, client_p->name, aconf->reason);
360 >      sendto_one(client_p, ":%s NOTICE %s :*** Banned: %s",
361 >                 me.name, client_p->name, conf->reason);
362        return(BANNED_CLIENT);
363      }
364    }
# Line 989 | Line 374 | verify_access(struct Client *client_p, c
374   * side effects - do actual attach
375   */
376   static int
377 < attach_iline(struct Client *client_p, struct ConfItem *conf)
377 > attach_iline(struct Client *client_p, struct MaskItem *conf)
378   {
379 <  struct AccessItem *aconf;
995 <  struct ClassItem *aclass;
379 >  struct ClassItem *class = NULL;
380    struct ip_entry *ip_found;
381    int a_limit_reached = 0;
382 <  int local = 0, global = 0, ident = 0;
382 >  unsigned int local = 0, global = 0, ident = 0;
383  
384    ip_found = find_or_add_ip(&client_p->localClient->ip);
385    ip_found->count++;
386    SetIpHash(client_p);
387  
388 <  aconf = map_to_conf(conf);
1005 <  if (aconf->class_ptr == NULL)
388 >  if (conf->class == NULL)
389      return NOT_AUTHORIZED;  /* If class is missing, this is best */
390  
391 <  aclass = map_to_conf(aconf->class_ptr);
391 >  class = conf->class;
392  
393    count_user_host(client_p->username, client_p->host,
394                    &global, &local, &ident);
# Line 1014 | Line 397 | attach_iline(struct Client *client_p, st
397     * setting a_limit_reached if any limit is reached.
398     * - Dianora
399     */
400 <  if (aclass->max_total != 0 && aclass->curr_user_count >= aclass->max_total)
400 >  if (class->max_total != 0 && class->ref_count >= class->max_total)
401      a_limit_reached = 1;
402 <  else if (aclass->max_perip != 0 && ip_found->count > aclass->max_perip)
402 >  else if (class->max_perip != 0 && ip_found->count > class->max_perip)
403      a_limit_reached = 1;
404 <  else if (aclass->max_local != 0 && local >= aclass->max_local)
404 >  else if (class->max_local != 0 && local >= class->max_local)
405      a_limit_reached = 1;
406 <  else if (aclass->max_global != 0 && global >= aclass->max_global)
406 >  else if (class->max_global != 0 && global >= class->max_global)
407      a_limit_reached = 1;
408 <  else if (aclass->max_ident != 0 && ident >= aclass->max_ident &&
408 >  else if (class->max_ident != 0 && ident >= class->max_ident &&
409             client_p->username[0] != '~')
410      a_limit_reached = 1;
411  
412    if (a_limit_reached)
413    {
414 <    if (!IsConfExemptLimits(aconf))
414 >    if (!IsConfExemptLimits(conf))
415        return TOO_MANY;   /* Already at maximum allowed */
416  
417      sendto_one(client_p,
# Line 1049 | Line 432 | attach_iline(struct Client *client_p, st
432   void
433   init_ip_hash_table(void)
434   {
435 <  ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
1053 <    2 * hard_fdlimit);
435 >  ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
436    memset(ip_hash_table, 0, sizeof(ip_hash_table));
437   }
438  
# Line 1099 | Line 481 | find_or_add_ip(struct irc_ssaddr *ip_in)
481    if (ip_entries_count >= 2 * hard_fdlimit)
482      garbage_collect_ip_entries();
483  
484 <  newptr = BlockHeapAlloc(ip_entry_heap);
484 >  newptr = mp_pool_get(ip_entry_pool);
485 >  memset(newptr, 0, sizeof(*newptr));
486    ip_entries_count++;
487    memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
488  
# Line 1157 | Line 540 | remove_one_ip(struct irc_ssaddr *ip_in)
540        else
541          ip_hash_table[hash_index] = ptr->next;
542  
543 <      BlockHeapFree(ip_entry_heap, ptr);
543 >      mp_pool_release(ptr);
544        ip_entries_count--;
545        return;
546      }
# Line 1260 | Line 643 | garbage_collect_ip_entries(void)
643            last_ptr->next = ptr->next;
644          else
645            ip_hash_table[i] = ptr->next;
646 <        BlockHeapFree(ip_entry_heap, ptr);
646 >        mp_pool_release(ptr);
647          ip_entries_count--;
648        }
649        else
# Line 1277 | Line 660 | garbage_collect_ip_entries(void)
660   * side effects - Disassociate configuration from the client.
661   *                Also removes a class from the list if marked for deleting.
662   */
663 < int
664 < detach_conf(struct Client *client_p, ConfType type)
663 > void
664 > detach_conf(struct Client *client_p, enum maskitem_type type)
665   {
666 <  dlink_node *ptr, *next_ptr;
1284 <  struct ConfItem *conf;
1285 <  struct ClassItem *aclass;
1286 <  struct AccessItem *aconf;
1287 <  struct ConfItem *aclass_conf;
1288 <  struct MatchItem *match_item;
666 >  dlink_node *ptr = NULL, *next_ptr = NULL;
667  
668    DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
669    {
670 <    conf = ptr->data;
1293 <
1294 <    if (type == CONF_TYPE || conf->type == type)
1295 <    {
1296 <      dlinkDelete(ptr, &client_p->localClient->confs);
1297 <      free_dlink_node(ptr);
670 >    struct MaskItem *conf = ptr->data;
671  
672 <      switch (conf->type)
673 <      {
674 <      case CLIENT_TYPE:
1302 <      case OPER_TYPE:
1303 <      case SERVER_TYPE:
1304 <        aconf = map_to_conf(conf);
1305 <
1306 <        assert(aconf->clients > 0);
672 >    assert(conf->type & (CONF_CLIENT | CONF_OPER | CONF_SERVER));
673 >    assert(conf->ref_count > 0);
674 >    assert(conf->class->ref_count > 0);
675  
676 <        if ((aclass_conf = aconf->class_ptr) != NULL)
677 <        {
1310 <          aclass = map_to_conf(aclass_conf);
1311 <
1312 <          assert(aclass->curr_user_count > 0);
1313 <
1314 <          if (conf->type == CLIENT_TYPE)
1315 <            remove_from_cidr_check(&client_p->localClient->ip, aclass);
1316 <          if (--aclass->curr_user_count == 0 && aclass->active == 0)
1317 <            delete_conf_item(aclass_conf);
1318 <        }
1319 <
1320 <        if (--aconf->clients == 0 && IsConfIllegal(aconf))
1321 <          delete_conf_item(conf);
676 >    if (!(conf->type & type))
677 >      continue;
678  
679 <        break;
679 >    dlinkDelete(ptr, &client_p->localClient->confs);
680 >    free_dlink_node(ptr);
681  
682 <      case LEAF_TYPE:
683 <      case HUB_TYPE:
1327 <        match_item = map_to_conf(conf);
1328 <        if (match_item->ref_count == 0 && match_item->illegal)
1329 <          delete_conf_item(conf);
1330 <        break;
1331 <      default:
1332 <        break;
1333 <      }
682 >    if (conf->type == CONF_CLIENT)
683 >      remove_from_cidr_check(&client_p->localClient->ip, conf->class);
684  
685 <      if (type != CONF_TYPE)
686 <        return 0;
685 >    if (--conf->class->ref_count == 0 && conf->class->active == 0)
686 >    {
687 >      class_free(conf->class);
688 >      conf->class = NULL;
689      }
1338  }
690  
691 <  return -1;
691 >    if (--conf->ref_count == 0 && conf->active == 0)
692 >      conf_free(conf);
693 >  }
694   }
695  
696   /* attach_conf()
# Line 1351 | Line 704 | detach_conf(struct Client *client_p, Con
704   *                attachment if there was an old one...
705   */
706   int
707 < attach_conf(struct Client *client_p, struct ConfItem *conf)
707 > attach_conf(struct Client *client_p, struct MaskItem *conf)
708   {
709    if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
710      return 1;
711  
712 <  if (conf->type == CLIENT_TYPE ||
713 <      conf->type == SERVER_TYPE ||
714 <      conf->type == OPER_TYPE)
715 <  {
1363 <    struct AccessItem *aconf = map_to_conf(conf);
1364 <    struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1365 <
1366 <    if (IsConfIllegal(aconf))
1367 <      return NOT_AUTHORIZED;
712 >  if (conf->type == CONF_CLIENT)
713 >    if (cidr_limit_reached(IsConfExemptLimits(conf),
714 >                           &client_p->localClient->ip, conf->class))
715 >      return TOO_MANY;    /* Already at maximum allowed */
716  
717 <    if (conf->type == CLIENT_TYPE)
718 <      if (cidr_limit_reached(IsConfExemptLimits(aconf),
1371 <                             &client_p->localClient->ip, aclass))
1372 <        return TOO_MANY;    /* Already at maximum allowed */
1373 <
1374 <    aclass->curr_user_count++;
1375 <    aconf->clients++;
1376 <  }
1377 <  else if (conf->type == HUB_TYPE || conf->type == LEAF_TYPE)
1378 <  {
1379 <    struct MatchItem *match_item = map_to_conf(conf);
1380 <    match_item->ref_count++;
1381 <  }
717 >  conf->class->ref_count++;
718 >  conf->ref_count++;
719  
720    dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
721  
# Line 1398 | Line 735 | attach_connect_block(struct Client *clie
735                       const char *host)
736   {
737    dlink_node *ptr;
738 <  struct ConfItem *conf;
1402 <  struct AccessItem *aconf;
738 >  struct MaskItem *conf = NULL;
739  
740    assert(client_p != NULL);
741    assert(host != NULL);
# Line 1410 | Line 746 | attach_connect_block(struct Client *clie
746    DLINK_FOREACH(ptr, server_items.head)
747    {
748      conf = ptr->data;
1413    aconf = map_to_conf(conf);
749  
750 <    if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
750 >    if (match(conf->name, name) || match(conf->host, host))
751        continue;
752  
753      attach_conf(client_p, conf);
# Line 1422 | Line 757 | attach_connect_block(struct Client *clie
757    return 0;
758   }
759  
1425 /* find_conf_exact()
1426 *
1427 * inputs       - type of ConfItem
1428 *              - pointer to name to find
1429 *              - pointer to username to find
1430 *              - pointer to host to find
1431 * output       - NULL or pointer to conf found
1432 * side effects - find a conf entry which matches the hostname
1433 *                and has the same name.
1434 */
1435 struct ConfItem *
1436 find_conf_exact(ConfType type, const char *name, const char *user,
1437                const char *host)
1438 {
1439  dlink_node *ptr;
1440  dlink_list *list_p;
1441  struct ConfItem *conf = NULL;
1442  struct AccessItem *aconf;
1443
1444  /* Only valid for OPER_TYPE and ...? */
1445  list_p = map_to_list(type);
1446
1447  DLINK_FOREACH(ptr, (*list_p).head)
1448  {
1449    conf = ptr->data;
1450
1451    if (conf->name == NULL)
1452      continue;
1453    aconf = map_to_conf(conf);
1454    if (aconf->host == NULL)
1455      continue;
1456    if (irccmp(conf->name, name) != 0)
1457      continue;
1458
1459    /*
1460    ** Accept if the *real* hostname (usually sockethost)
1461    ** socket host) matches *either* host or name field
1462    ** of the configuration.
1463    */
1464    if (!match(aconf->host, host) || !match(aconf->user, user))
1465      continue;
1466    if (type == OPER_TYPE)
1467    {
1468      struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1469
1470      if (aconf->clients >= aclass->max_total)
1471        continue;
1472    }
1473
1474    return conf;
1475  }
1476
1477  return NULL;
1478 }
1479
760   /* find_conf_name()
761   *
762   * inputs       - pointer to conf link list to search
# Line 1486 | Line 766 | find_conf_exact(ConfType type, const cha
766   * side effects - find a conf entry which matches the name
767   *                and has the given mask.
768   */
769 < struct ConfItem *
770 < find_conf_name(dlink_list *list, const char *name, ConfType type)
769 > struct MaskItem *
770 > find_conf_name(dlink_list *list, const char *name, enum maskitem_type type)
771   {
772    dlink_node *ptr;
773 <  struct ConfItem* conf;
773 >  struct MaskItem* conf;
774  
775    DLINK_FOREACH(ptr, list->head)
776    {
# Line 1499 | Line 779 | find_conf_name(dlink_list *list, const c
779      if (conf->type == type)
780      {
781        if (conf->name && (irccmp(conf->name, name) == 0 ||
782 <                         match(conf->name, name)))
782 >                         !match(conf->name, name)))
783        return conf;
784      }
785    }
# Line 1514 | Line 794 | find_conf_name(dlink_list *list, const c
794   * side effects - none
795   */
796   static dlink_list *
797 < map_to_list(ConfType type)
797 > map_to_list(enum maskitem_type type)
798   {
799    switch(type)
800    {
801 <  case RXLINE_TYPE:
1522 <    return(&rxconf_items);
1523 <    break;
1524 <  case XLINE_TYPE:
801 >  case CONF_XLINE:
802      return(&xconf_items);
803      break;
804 <  case ULINE_TYPE:
804 >  case CONF_ULINE:
805      return(&uconf_items);
806      break;
807 <  case NRESV_TYPE:
807 >  case CONF_NRESV:
808      return(&nresv_items);
809      break;
810 <  case OPER_TYPE:
810 >  case CONF_CRESV:
811 >    return(&resv_channel_list);
812 >  case CONF_OPER:
813      return(&oconf_items);
814      break;
815 <  case CLASS_TYPE:
1537 <    return(&class_items);
1538 <    break;
1539 <  case SERVER_TYPE:
815 >  case CONF_SERVER:
816      return(&server_items);
817      break;
818 <  case SERVICE_TYPE:
818 >  case CONF_SERVICE:
819      return(&service_items);
820      break;
821 <  case CLUSTER_TYPE:
821 >  case CONF_CLUSTER:
822      return(&cluster_items);
823      break;
1548  case CONF_TYPE:
1549  case GLINE_TYPE:
1550  case KLINE_TYPE:
1551  case DLINE_TYPE:
1552  case CRESV_TYPE:
824    default:
825      return NULL;
826    }
# Line 1561 | Line 832 | map_to_list(ConfType type)
832   *              - pointer to name string to find
833   *              - pointer to user
834   *              - pointer to host
835 < *              - optional action to match on as well
836 < * output       - NULL or pointer to found struct MatchItem
835 > *              - optional flags to match on as well
836 > * output       - NULL or pointer to found struct MaskItem
837   * side effects - looks for a match on name field
838   */
839 < struct ConfItem *
840 < find_matching_name_conf(ConfType type, const char *name, const char *user,
841 <                        const char *host, int action)
839 > struct MaskItem *
840 > find_matching_name_conf(enum maskitem_type type, const char *name, const char *user,
841 >                        const char *host, unsigned int flags)
842   {
843    dlink_node *ptr=NULL;
844 <  struct ConfItem *conf=NULL;
1574 <  struct AccessItem *aconf=NULL;
1575 <  struct MatchItem *match_item=NULL;
844 >  struct MaskItem *conf=NULL;
845    dlink_list *list_p = map_to_list(type);
846  
847    switch (type)
848    {
849 < #ifdef HAVE_LIBPCRE
1581 <  case RXLINE_TYPE:
1582 <      DLINK_FOREACH(ptr, list_p->head)
1583 <      {
1584 <        conf = ptr->data;
1585 <        assert(conf->regexpname);
1586 <
1587 <        if (!ircd_pcre_exec(conf->regexpname, name))
1588 <          return conf;
1589 <      }
1590 <      break;
1591 < #endif
1592 <  case SERVICE_TYPE:
849 >  case CONF_SERVICE:
850      DLINK_FOREACH(ptr, list_p->head)
851      {
852        conf = ptr->data;
# Line 1601 | Line 858 | find_matching_name_conf(ConfType type, c
858      }
859      break;
860  
861 <  case XLINE_TYPE:
862 <  case ULINE_TYPE:
863 <  case NRESV_TYPE:
861 >  case CONF_XLINE:
862 >  case CONF_ULINE:
863 >  case CONF_NRESV:
864 >  case CONF_CRESV:
865      DLINK_FOREACH(ptr, list_p->head)
866      {
867        conf = ptr->data;
868  
1611      match_item = map_to_conf(conf);
869        if (EmptyString(conf->name))
870          continue;
871 <      if ((name != NULL) && match_esc(conf->name, name))
871 >      if ((name != NULL) && !match(conf->name, name))
872        {
873          if ((user == NULL && (host == NULL)))
874            return conf;
875 <        if ((match_item->action & action) != action)
875 >        if ((conf->flags & flags) != flags)
876            continue;
877 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
877 >        if (EmptyString(conf->user) || EmptyString(conf->host))
878            return conf;
879 <        if (match(match_item->user, user) && match(match_item->host, host))
879 >        if (!match(conf->user, user) && !match(conf->host, host))
880            return conf;
881        }
882      }
883        break;
884  
885 <  case SERVER_TYPE:
885 >  case CONF_SERVER:
886      DLINK_FOREACH(ptr, list_p->head)
887      {
888        conf = ptr->data;
1632      aconf = map_to_conf(conf);
889  
890 <      if ((name != NULL) && match_esc(name, conf->name))
890 >      if ((name != NULL) && !match(name, conf->name))
891          return conf;
892 <      else if ((host != NULL) && match_esc(host, aconf->host))
892 >      else if ((host != NULL) && !match(host, conf->host))
893          return conf;
894      }
895      break;
# Line 1650 | Line 906 | find_matching_name_conf(ConfType type, c
906   *              - pointer to name string to find
907   *              - pointer to user
908   *              - pointer to host
909 < * output       - NULL or pointer to found struct MatchItem
909 > * output       - NULL or pointer to found struct MaskItem
910   * side effects - looks for an exact match on name field
911   */
912 < struct ConfItem *
913 < find_exact_name_conf(ConfType type, const struct Client *who, const char *name,
912 > struct MaskItem *
913 > find_exact_name_conf(enum maskitem_type type, const struct Client *who, const char *name,
914                       const char *user, const char *host)
915   {
916    dlink_node *ptr = NULL;
917 <  struct AccessItem *aconf;
918 <  struct ConfItem *conf;
1663 <  struct MatchItem *match_item;
1664 <  dlink_list *list_p;
1665 <
1666 <  list_p = map_to_list(type);
917 >  struct MaskItem *conf;
918 >  dlink_list *list_p = map_to_list(type);
919  
920    switch(type)
921    {
922 <  case RXLINE_TYPE:
923 <  case XLINE_TYPE:
924 <  case ULINE_TYPE:
925 <  case NRESV_TYPE:
922 >  case CONF_XLINE:
923 >  case CONF_ULINE:
924 >  case CONF_NRESV:
925 >  case CONF_CRESV:
926  
927      DLINK_FOREACH(ptr, list_p->head)
928      {
929        conf = ptr->data;
930 <      match_item = (struct MatchItem *)map_to_conf(conf);
930 >
931        if (EmptyString(conf->name))
932          continue;
933      
# Line 1683 | Line 935 | find_exact_name_conf(ConfType type, cons
935        {
936          if ((user == NULL && (host == NULL)))
937            return (conf);
938 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
938 >        if (EmptyString(conf->user) || EmptyString(conf->host))
939            return (conf);
940 <        if (match(match_item->user, user) && match(match_item->host, host))
940 >        if (!match(conf->user, user) && !match(conf->host, host))
941            return (conf);
942        }
943      }
944      break;
945  
946 <  case OPER_TYPE:
946 >  case CONF_OPER:
947      DLINK_FOREACH(ptr, list_p->head)
948      {
949        conf = ptr->data;
1698      aconf = map_to_conf(conf);
950  
951        if (EmptyString(conf->name))
952          continue;
# Line 1704 | Line 955 | find_exact_name_conf(ConfType type, cons
955        {
956          if (!who)
957            return conf;
958 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
959 <          return conf;
960 <        if (match(aconf->user, who->username))
958 >        if (EmptyString(conf->user) || EmptyString(conf->host))
959 >          return NULL;
960 >        if (!match(conf->user, who->username))
961          {
962 <          switch (aconf->type)
962 >          switch (conf->htype)
963            {
964              case HM_HOST:
965 <              if (match(aconf->host, who->host) || match(aconf->host, who->sockhost))
966 <                return conf;
965 >              if (!match(conf->host, who->host) || !match(conf->host, who->sockhost))
966 >                if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
967 >                  return conf;
968                break;
969              case HM_IPV4:
970                if (who->localClient->aftype == AF_INET)
971 <                if (match_ipv4(&who->localClient->ip, &aconf->ipnum, aconf->bits))
972 <                  return conf;
971 >                if (match_ipv4(&who->localClient->ip, &conf->addr, conf->bits))
972 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
973 >                    return conf;
974                break;
975   #ifdef IPV6
976              case HM_IPV6:
977                if (who->localClient->aftype == AF_INET6)
978 <                if (match_ipv6(&who->localClient->ip, &aconf->ipnum, aconf->bits))
979 <                  return conf;
978 >                if (match_ipv6(&who->localClient->ip, &conf->addr, conf->bits))
979 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
980 >                    return conf;
981                break;
982   #endif
983              default:
# Line 1735 | Line 989 | find_exact_name_conf(ConfType type, cons
989  
990      break;
991  
992 <  case SERVER_TYPE:
992 >  case CONF_SERVER:
993      DLINK_FOREACH(ptr, list_p->head)
994      {
995        conf = ptr->data;
996 <      aconf = (struct AccessItem *)map_to_conf(conf);
996 >
997        if (EmptyString(conf->name))
998          continue;
999      
1000        if (name == NULL)
1001        {
1002 <        if (EmptyString(aconf->host))
1002 >        if (EmptyString(conf->host))
1003            continue;
1004 <        if (irccmp(aconf->host, host) == 0)
1004 >        if (irccmp(conf->host, host) == 0)
1005            return(conf);
1006        }
1007        else if (irccmp(conf->name, name) == 0)
# Line 1757 | Line 1011 | find_exact_name_conf(ConfType type, cons
1011      }
1012      break;
1013  
1760  case CLASS_TYPE:
1761    DLINK_FOREACH(ptr, list_p->head)
1762    {
1763      conf = ptr->data;
1764      if (EmptyString(conf->name))
1765        continue;
1766    
1767      if (irccmp(conf->name, name) == 0)
1768        return (conf);
1769    }
1770    break;
1771
1014    default:
1015      break;
1016    }
# Line 1785 | Line 1027 | int
1027   rehash(int sig)
1028   {
1029    if (sig != 0)
1030 <    sendto_realops_flags(UMODE_ALL, L_ALL,
1030 >    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1031                           "Got signal SIGHUP, reloading ircd.conf file");
1032  
1033    restart_resolver();
# Line 1802 | Line 1044 | rehash(int sig)
1044  
1045    load_conf_modules();
1046  
1805  flush_deleted_I_P();
1806
1047    rehashed_klines = 1;
1808 /* XXX */
1809  if (ConfigLoggingEntry.use_logging)
1810    log_close_all();
1048  
1049 <  return(0);
1049 >  return 0;
1050   }
1051  
1052   /* set_default_conf()
# Line 1827 | Line 1064 | set_default_conf(void)
1064    /* verify init_class() ran, this should be an unnecessary check
1065     * but its not much work.
1066     */
1067 <  assert(class_default == (struct ConfItem *) class_items.tail->data);
1067 >  assert(class_default == class_get_list()->tail->data);
1068  
1069   #ifdef HAVE_LIBCRYPTO
1070    ServerInfo.rsa_private_key = NULL;
# Line 1837 | Line 1074 | set_default_conf(void)
1074    /* ServerInfo.name is not rehashable */
1075    /* ServerInfo.name = ServerInfo.name; */
1076    ServerInfo.description = NULL;
1077 <  DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1078 <  DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1077 >  ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1078 >  ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1079  
1080    memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1081    ServerInfo.specific_ipv4_vhost = 0;
# Line 1846 | Line 1083 | set_default_conf(void)
1083    ServerInfo.specific_ipv6_vhost = 0;
1084  
1085    ServerInfo.max_clients = MAXCLIENTS_MAX;
1086 +  ServerInfo.max_nick_length = 9;
1087 +  ServerInfo.max_topic_length = 80;
1088  
1089    ServerInfo.hub = 0;
1090    ServerInfo.dns_host.sin_addr.s_addr = 0;
# Line 1854 | Line 1093 | set_default_conf(void)
1093    AdminInfo.email = NULL;
1094    AdminInfo.description = NULL;
1095  
1096 <  log_close_all();
1096 >  log_del_all();
1097  
1098    ConfigLoggingEntry.use_logging = 1;
1099  
1100    ConfigChannel.disable_fake_channels = 0;
1862  ConfigChannel.restrict_channels = 0;
1863  ConfigChannel.disable_local_channels = 0;
1864  ConfigChannel.use_invex = 1;
1865  ConfigChannel.use_except = 1;
1866  ConfigChannel.use_knock = 1;
1101    ConfigChannel.knock_delay = 300;
1102    ConfigChannel.knock_delay_channel = 60;
1103 <  ConfigChannel.max_chans_per_user = 15;
1104 <  ConfigChannel.quiet_on_ban = 1;
1103 >  ConfigChannel.max_chans_per_user = 25;
1104 >  ConfigChannel.max_chans_per_oper = 50;
1105    ConfigChannel.max_bans = 25;
1106    ConfigChannel.default_split_user_count = 0;
1107    ConfigChannel.default_split_server_count = 0;
1108    ConfigChannel.no_join_on_split = 0;
1109    ConfigChannel.no_create_on_split = 0;
1876  ConfigChannel.burst_topicwho = 1;
1110  
1111    ConfigServerHide.flatten_links = 0;
1112    ConfigServerHide.links_delay = 300;
1113    ConfigServerHide.hidden = 0;
1881  ConfigServerHide.disable_hidden = 0;
1114    ConfigServerHide.hide_servers = 0;
1115 <  DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1115 >  ConfigServerHide.hide_services = 0;
1116 >  ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
1117    ConfigServerHide.hide_server_ips = 0;
1118  
1119    
1120 <  DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1120 >  ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1121    ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1122 +  ConfigFileEntry.glines = 0;
1123 +  ConfigFileEntry.gline_time = 12 * 3600;
1124 +  ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
1125    ConfigFileEntry.gline_min_cidr = 16;
1126    ConfigFileEntry.gline_min_cidr6 = 48;
1127    ConfigFileEntry.invisible_on_connect = 1;
1892  ConfigFileEntry.burst_away = 0;
1893  ConfigFileEntry.use_whois_actually = 1;
1128    ConfigFileEntry.tkline_expire_notices = 1;
1129    ConfigFileEntry.hide_spoof_ips = 1;
1130    ConfigFileEntry.ignore_bogus_ts = 0;
# Line 1909 | Line 1143 | set_default_conf(void)
1143    ConfigFileEntry.anti_spam_exit_message_time = 0;
1144    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1145    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1912  ConfigFileEntry.kline_with_reason = 1;
1913  ConfigFileEntry.kline_reason = NULL;
1146    ConfigFileEntry.warn_no_nline = 1;
1147    ConfigFileEntry.stats_o_oper_only = 0;
1148    ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
# Line 1925 | Line 1157 | set_default_conf(void)
1157    ConfigFileEntry.no_oper_flood = 0;
1158    ConfigFileEntry.true_no_oper_flood = 0;
1159    ConfigFileEntry.oper_pass_resv = 1;
1928  ConfigFileEntry.glines = 0;
1929  ConfigFileEntry.gline_time = 12 * 3600;
1160    ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1931  ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1161    ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1162    ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1163      UMODE_OPERWALL | UMODE_WALLOP;
# Line 1947 | Line 1176 | validate_conf(void)
1176      ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1177  
1178    if (ServerInfo.network_name == NULL)
1179 <    DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1179 >    ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1180  
1181    if (ServerInfo.network_desc == NULL)
1182 <    DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1182 >    ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1183  
1184    if (ConfigFileEntry.service_name == NULL)
1185 <    DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1957 <
1958 <  if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1959 <      (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1960 <    ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1185 >    ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1186  
1187    ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1188   }
# Line 1983 | Line 1208 | read_conf(FILE *file)
1208    yyparse();          /* Load the values from the conf */
1209    validate_conf();    /* Check to make sure some values are still okay. */
1210                        /* Some global values are also loaded here. */
1211 <  check_class();      /* Make sure classes are valid */
1211 >  class_delete_marked();      /* Make sure classes are valid */
1212   }
1213  
1214   /* lookup_confhost()
# Line 1991 | Line 1216 | read_conf(FILE *file)
1216   * start DNS lookups of all hostnames in the conf
1217   * line and convert an IP addresses in a.b.c.d number for to IP#s.
1218   */
1219 < static void
1220 < lookup_confhost(struct ConfItem *conf)
1219 > void
1220 > lookup_confhost(struct MaskItem *conf)
1221   {
1997  struct AccessItem *aconf;
1222    struct addrinfo hints, *res;
1223  
2000  aconf = map_to_conf(conf);
2001
2002  if (EmptyString(aconf->host) ||
2003      EmptyString(aconf->user))
2004  {
2005    ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
2006         aconf->host, conf->name);
2007    return;
2008  }
2009
2010  if (strchr(aconf->host, '*') ||
2011      strchr(aconf->host, '?'))
2012    return;
2013
1224    /* Do name lookup now on hostnames given and store the
1225     * ip numbers in conf structure.
1226     */
# Line 2022 | Line 1232 | lookup_confhost(struct ConfItem *conf)
1232    /* Get us ready for a bind() and don't bother doing dns lookup */
1233    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1234  
1235 <  if (getaddrinfo(aconf->host, NULL, &hints, &res))
1235 >  if (getaddrinfo(conf->host, NULL, &hints, &res))
1236    {
1237 <    conf_dns_lookup(aconf);
1237 >    conf_dns_lookup(conf);
1238      return;
1239    }
1240  
1241    assert(res != NULL);
1242  
1243 <  memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
1244 <  aconf->ipnum.ss_len = res->ai_addrlen;
1245 <  aconf->ipnum.ss.ss_family = res->ai_family;
1243 >  memcpy(&conf->addr, res->ai_addr, res->ai_addrlen);
1244 >  conf->addr.ss_len = res->ai_addrlen;
1245 >  conf->addr.ss.ss_family = res->ai_family;
1246 >
1247    freeaddrinfo(res);
1248   }
1249  
# Line 2047 | Line 1258 | int
1258   conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1259   {
1260    struct ip_entry *ip_found;
1261 <  struct AccessItem *aconf = find_dline_conf(addr, aftype);
1261 >  struct MaskItem *conf = find_dline_conf(addr, aftype);
1262  
1263    /* DLINE exempt also gets you out of static limits/pacing... */
1264 <  if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1264 >  if (conf && (conf->type == CONF_EXEMPT))
1265      return 0;
1266  
1267 <  if (aconf != NULL)
1267 >  if (conf != NULL)
1268      return BANNED_CLIENT;
1269  
1270    ip_found = find_or_add_ip(addr);
# Line 2069 | Line 1280 | conf_connect_allowed(struct irc_ssaddr *
1280    return 0;
1281   }
1282  
2072 static struct AccessItem *
2073 find_regexp_kline(const char *uhi[])
2074 {
2075 #ifdef HAVE_LIBPCRE
2076  const dlink_node *ptr = NULL;
2077
2078  DLINK_FOREACH(ptr, rkconf_items.head)
2079  {
2080    struct AccessItem *aptr = map_to_conf(ptr->data);
2081
2082    assert(aptr->regexuser);
2083    assert(aptr->regexhost);
2084
2085    if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2086        (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2087         !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2088      return aptr;
2089  }
2090 #endif
2091  return NULL;
2092 }
2093
1283   /* find_kill()
1284   *
1285   * inputs       - pointer to client structure
1286 < * output       - pointer to struct AccessItem if found
1286 > * output       - pointer to struct MaskItem if found
1287   * side effects - See if this user is klined already,
1288 < *                and if so, return struct AccessItem pointer
1288 > *                and if so, return struct MaskItem pointer
1289   */
1290 < struct AccessItem *
1290 > struct MaskItem *
1291   find_kill(struct Client *client_p)
1292   {
1293 <  struct AccessItem *aconf = NULL;
2105 <  const char *uhi[3];
2106 <
2107 <  uhi[0] = client_p->username;
2108 <  uhi[1] = client_p->host;
2109 <  uhi[2] = client_p->sockhost;
1293 >  struct MaskItem *conf = NULL;
1294  
1295    assert(client_p != NULL);
1296  
1297 <  aconf = find_kline_conf(client_p->host, client_p->username,
1298 <                          &client_p->localClient->ip,
1299 <                          client_p->localClient->aftype);
1300 <  if (aconf == NULL)
2117 <    aconf = find_regexp_kline(uhi);
2118 <
2119 <  if (aconf && (aconf->status & CONF_KLINE))
2120 <    return aconf;
2121 <
2122 <  return NULL;
1297 >  conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1298 >                              CONF_KLINE, client_p->localClient->aftype,
1299 >                              client_p->username, NULL, 1);
1300 >  return conf;
1301   }
1302  
1303 < struct AccessItem *
1303 > struct MaskItem *
1304   find_gline(struct Client *client_p)
1305   {
1306 <  struct AccessItem *aconf;
1306 >  struct MaskItem *conf;
1307  
1308    assert(client_p != NULL);
1309  
1310 <  aconf = find_gline_conf(client_p->host, client_p->username,
1311 <                          &client_p->localClient->ip,
1312 <                          client_p->localClient->aftype);
1313 <
2136 <  if (aconf && (aconf->status & CONF_GLINE))
2137 <    return aconf;
2138 <
2139 <  return NULL;
2140 < }
2141 <
2142 < /* add_temp_line()
2143 < *
2144 < * inputs        - pointer to struct ConfItem
2145 < * output        - none
2146 < * Side effects  - links in given struct ConfItem into
2147 < *                 temporary *line link list
2148 < */
2149 < void
2150 < add_temp_line(struct ConfItem *conf)
2151 < {
2152 <  if (conf->type == XLINE_TYPE)
2153 <  {
2154 <    conf->flags |= CONF_FLAGS_TEMPORARY;
2155 <    dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2156 <  }
2157 <  else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2158 <  {
2159 <    conf->flags |= CONF_FLAGS_TEMPORARY;
2160 <    dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2161 <  }
1310 >  conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1311 >                              CONF_GLINE, client_p->localClient->aftype,
1312 >                              client_p->username, NULL, 1);
1313 >  return conf;
1314   }
1315  
1316   /* cleanup_tklines()
# Line 2172 | Line 1324 | void
1324   cleanup_tklines(void *notused)
1325   {
1326    hostmask_expire_temporary();
1327 <  expire_tklines(&temporary_xlines);
1328 <  expire_tklines(&temporary_resv);
1327 >  expire_tklines(&xconf_items);
1328 >  expire_tklines(&nresv_items);
1329 >  expire_tklines(&resv_channel_list);
1330   }
1331  
1332   /* expire_tklines()
# Line 2187 | Line 1340 | expire_tklines(dlink_list *tklist)
1340   {
1341    dlink_node *ptr;
1342    dlink_node *next_ptr;
1343 <  struct ConfItem *conf;
2191 <  struct MatchItem *xconf;
2192 <  struct MatchItem *nconf;
2193 <  struct ResvChannel *cconf;
1343 >  struct MaskItem *conf;
1344  
1345    DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
1346    {
1347      conf = ptr->data;
1348  
1349 <    if (conf->type == XLINE_TYPE)
1349 >    if (!conf->until || conf->until > CurrentTime)
1350 >      continue;
1351 >
1352 >    if (conf->type == CONF_XLINE)
1353      {
1354 <      xconf = (struct MatchItem *)map_to_conf(conf);
1355 <      if (xconf->hold <= CurrentTime)
1356 <      {
1357 <        if (ConfigFileEntry.tkline_expire_notices)
2205 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2206 <                               "Temporary X-line for [%s] sexpired", conf->name);
2207 <        dlinkDelete(ptr, tklist);
2208 <        free_dlink_node(ptr);
2209 <        delete_conf_item(conf);
2210 <      }
1354 >      if (ConfigFileEntry.tkline_expire_notices)
1355 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1356 >                               "Temporary X-line for [%s] expired", conf->name);
1357 >      conf_free(conf);
1358      }
1359 <    else if (conf->type == NRESV_TYPE)
1359 >    else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1360      {
1361 <      nconf = (struct MatchItem *)map_to_conf(conf);
1362 <      if (nconf->hold <= CurrentTime)
2216 <      {
2217 <        if (ConfigFileEntry.tkline_expire_notices)
2218 <          sendto_realops_flags(UMODE_ALL, L_ALL,
1361 >      if (ConfigFileEntry.tkline_expire_notices)
1362 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1363                                 "Temporary RESV for [%s] expired", conf->name);
1364 <        dlinkDelete(ptr, tklist);
2221 <        free_dlink_node(ptr);
2222 <        delete_conf_item(conf);
2223 <      }
2224 <    }
2225 <    else if (conf->type == CRESV_TYPE)
2226 <    {
2227 <      cconf = (struct ResvChannel *)map_to_conf(conf);
2228 <      if (cconf->hold <= CurrentTime)
2229 <      {
2230 <        if (ConfigFileEntry.tkline_expire_notices)
2231 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2232 <                               "Temporary RESV for [%s] expired", cconf->name);
2233 <        delete_channel_resv(cconf);
2234 <      }
1364 >      conf_free(conf);
1365      }
1366    }
1367   }
# Line 2244 | Line 1374 | expire_tklines(dlink_list *tklist)
1374   */
1375   static const struct oper_privs
1376   {
1377 <  const unsigned int oprivs;
1377 >  const unsigned int flag;
1378    const unsigned char c;
1379   } flag_list[] = {
1380 <  { OPER_FLAG_ADMIN,       'A' },
1381 <  { OPER_FLAG_REMOTEBAN,   'B' },
1382 <  { OPER_FLAG_DIE,         'D' },
1383 <  { OPER_FLAG_GLINE,       'G' },
1384 <  { OPER_FLAG_REHASH,      'H' },
1385 <  { OPER_FLAG_K,           'K' },
1386 <  { OPER_FLAG_OPERWALL,    'L' },
1387 <  { OPER_FLAG_N,           'N' },
1388 <  { OPER_FLAG_GLOBAL_KILL, 'O' },
1389 <  { OPER_FLAG_REMOTE,      'R' },
1390 <  { OPER_FLAG_OPER_SPY,    'S' },
1391 <  { OPER_FLAG_UNKLINE,     'U' },
1392 <  { OPER_FLAG_X,           'X' },
1380 >  { OPER_FLAG_ADMIN,          'A' },
1381 >  { OPER_FLAG_REMOTEBAN,      'B' },
1382 >  { OPER_FLAG_DIE,            'D' },
1383 >  { OPER_FLAG_GLINE,          'G' },
1384 >  { OPER_FLAG_REHASH,         'H' },
1385 >  { OPER_FLAG_K,              'K' },
1386 >  { OPER_FLAG_OPERWALL,       'L' },
1387 >  { OPER_FLAG_KILL,           'N' },
1388 >  { OPER_FLAG_KILL_REMOTE,    'O' },
1389 >  { OPER_FLAG_CONNECT,        'P' },
1390 >  { OPER_FLAG_CONNECT_REMOTE, 'Q' },
1391 >  { OPER_FLAG_SQUIT,          'R' },
1392 >  { OPER_FLAG_SQUIT_REMOTE,   'S' },
1393 >  { OPER_FLAG_UNKLINE,        'U' },
1394 >  { OPER_FLAG_X,              'X' },
1395    { 0, '\0' }
1396   };
1397  
# Line 2268 | Line 1400 | oper_privs_as_string(const unsigned int
1400   {
1401    static char privs_out[16];
1402    char *privs_ptr = privs_out;
1403 <  unsigned int i = 0;
1403 >  const struct oper_privs *opriv = flag_list;
1404  
1405 <  for (; flag_list[i].oprivs; ++i)
1405 >  for (; opriv->flag; ++opriv)
1406    {
1407 <    if (port & flag_list[i].oprivs)
1408 <      *privs_ptr++ = flag_list[i].c;
1407 >    if (port & opriv->flag)
1408 >      *privs_ptr++ = opriv->c;
1409      else
1410 <      *privs_ptr++ = ToLowerTab[flag_list[i].c];
1410 >      *privs_ptr++ = ToLower(opriv->c);
1411    }
1412  
1413    *privs_ptr = '\0';
# Line 2300 | Line 1432 | get_oper_name(const struct Client *clien
1432    {
1433      if ((cnode = client_p->localClient->confs.head))
1434      {
1435 <      struct ConfItem *conf = cnode->data;
2304 <      const struct AccessItem *aconf = map_to_conf(conf);
1435 >      struct MaskItem *conf = cnode->data;
1436  
1437 <      if (IsConfOperator(aconf))
1437 >      if (IsConfOperator(conf))
1438        {
1439          snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1440                   client_p->username, client_p->host, conf->name);
# Line 2336 | Line 1467 | read_conf_files(int cold)
1467    char chanlimit[32];
1468  
1469    conf_parser_ctx.boot = cold;
1470 <  filename = get_conf_name(CONF_TYPE);
1470 >  filename = ConfigFileEntry.configfile;
1471  
1472    /* We need to know the initial filename for the yyerror() to report
1473       FIXME: The full path is in conffilenamebuf first time since we
# Line 2356 | Line 1487 | read_conf_files(int cold)
1487      }
1488      else
1489      {
1490 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1490 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1491                             "Unable to read configuration file '%s': %s",
1492                             filename, strerror(errno));
1493        return;
# Line 2369 | Line 1500 | read_conf_files(int cold)
1500    read_conf(conf_parser_ctx.conf_file);
1501    fclose(conf_parser_ctx.conf_file);
1502  
1503 +  log_reopen_all();
1504 +
1505 +  add_isupport("NICKLEN", NULL, ServerInfo.max_nick_length);
1506    add_isupport("NETWORK", ServerInfo.network_name, -1);
1507 <  snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
1508 <           ConfigChannel.use_except ? "e" : "",
2375 <           ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
1507 >
1508 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1509    add_isupport("MAXLIST", chanmodes, -1);
1510    add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1511 +  add_isupport("CHANTYPES", "#", -1);
1512  
1513 <  if (ConfigChannel.disable_local_channels)
1514 <    add_isupport("CHANTYPES", "#", -1);
2381 <  else
2382 <    add_isupport("CHANTYPES", "#&", -1);
2383 <
2384 <  snprintf(chanlimit, sizeof(chanlimit), "%s:%d",
2385 <           ConfigChannel.disable_local_channels ? "#" : "#&",
2386 <           ConfigChannel.max_chans_per_user);
1513 >  snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1514 >           ConfigChannel.max_chans_per_user);
1515    add_isupport("CHANLIMIT", chanlimit, -1);
1516 <  snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
2389 <           ConfigChannel.use_except ? "e" : "",
2390 <           ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
1516 >  snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,imnprstORS");
1517    add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
1518 <
1519 <  if (ConfigChannel.use_except)
1520 <    add_isupport("EXCEPTS", "e", -1);
2395 <  if (ConfigChannel.use_invex)
2396 <    add_isupport("INVEX", "I", -1);
1518 >  add_isupport("TOPICLEN", NULL, ServerInfo.max_topic_length);
1519 >  add_isupport("EXCEPTS", "e", -1);
1520 >  add_isupport("INVEX", "I", -1);
1521    add_isupport("CHANMODES", chanmodes, -1);
1522  
1523    /*
# Line 2401 | Line 1525 | read_conf_files(int cold)
1525     * on strlen(form_str(RPL_ISUPPORT))
1526     */
1527    rebuild_isupport_message_line();
2404
2405 #ifdef HAVE_LIBPCRE
2406  parse_conf_file(RKLINE_TYPE, cold);
2407  parse_conf_file(RXLINE_TYPE, cold);
2408 #endif
2409  parse_conf_file(KLINE_TYPE, cold);
2410  parse_conf_file(DLINE_TYPE, cold);
2411  parse_conf_file(XLINE_TYPE, cold);
2412  parse_conf_file(NRESV_TYPE, cold);
2413  parse_conf_file(CRESV_TYPE, cold);
2414 }
2415
2416 /* parse_conf_file()
2417 *
2418 * inputs       - type of conf file to parse
2419 * output       - none
2420 * side effects - conf file for givenconf type is opened and read then parsed
2421 */
2422 static void
2423 parse_conf_file(int type, int cold)
2424 {
2425  FILE *file = NULL;
2426  const char *filename = get_conf_name(type);
2427
2428  if ((file = fopen(filename, "r")) == NULL)
2429  {
2430    if (cold)
2431      ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2432           filename, strerror(errno));
2433    else
2434      sendto_realops_flags(UMODE_ALL, L_ALL,
2435                    "Unable to read configuration file '%s': %s",
2436                           filename, strerror(errno));
2437  }
2438  else
2439  {
2440    parse_csv_file(file, type);
2441    fclose(file);
2442  }
1528   }
1529  
1530   /* clear_out_old_conf()
# Line 2452 | Line 1537 | static void
1537   clear_out_old_conf(void)
1538   {
1539    dlink_node *ptr = NULL, *next_ptr = NULL;
1540 <  struct ConfItem *conf;
2456 <  struct AccessItem *aconf;
2457 <  struct ClassItem *cltmp;
2458 <  struct MatchItem *match_item;
1540 >  struct MaskItem *conf;
1541    dlink_list *free_items [] = {
1542 <    &server_items,   &oconf_items,    &hub_items, &leaf_items,
1543 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1544 <     &nresv_items, &cluster_items,  &gdeny_items, &service_items, NULL
1542 >    &server_items,   &oconf_items,
1543 >     &uconf_items,   &xconf_items,
1544 >     &nresv_items, &cluster_items,  &service_items, &resv_channel_list, NULL
1545    };
1546  
1547    dlink_list ** iterator = free_items; /* C is dumb */
# Line 2473 | Line 1555 | clear_out_old_conf(void)
1555      DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1556      {
1557        conf = ptr->data;
2476      /* XXX This is less than pretty */
2477      if (conf->type == SERVER_TYPE)
2478      {
2479        aconf = map_to_conf(conf);
1558  
1559 <        if (aconf->clients != 0)
2482 <        {
2483 <          SetConfIllegal(aconf);
2484 <          dlinkDelete(&conf->node, &server_items);
2485 <        }
2486 <        else
2487 <        {
2488 <          delete_conf_item(conf);
2489 <        }
2490 <      }
2491 <      else if (conf->type == OPER_TYPE)
2492 <      {
2493 <        aconf = map_to_conf(conf);
1559 >      dlinkDelete(&conf->node, map_to_list(conf->type));
1560  
1561 <        if (aconf->clients != 0)
1562 <        {
2497 <          SetConfIllegal(aconf);
2498 <          dlinkDelete(&conf->node, &oconf_items);
2499 <        }
2500 <        else
2501 <        {
2502 <          delete_conf_item(conf);
2503 <        }
2504 <      }
2505 <      else if (conf->type == XLINE_TYPE  ||
2506 <               conf->type == RXLINE_TYPE ||
2507 <               conf->type == RKLINE_TYPE)
1561 >      /* XXX This is less than pretty */
1562 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1563        {
1564 <        /* temporary (r)xlines are also on
1565 <         * the (r)xconf items list */
2511 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2512 <          continue;
2513 <
2514 <        delete_conf_item(conf);
1564 >        if (!conf->ref_count)
1565 >          conf_free(conf);
1566        }
1567 <      else
1567 >      else if (conf->type == CONF_XLINE)
1568        {
1569 <        if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
1570 <        {
2520 <          match_item = map_to_conf(conf);
2521 <          if (match_item->ref_count <= 0)
2522 <            delete_conf_item(conf);
2523 <          else
2524 <          {
2525 <            match_item->illegal = 1;
2526 <            dlinkDelete(&conf->node, *iterator);
2527 <          }
2528 <        }
2529 <        else
2530 <          delete_conf_item(conf);
1569 >        if (!conf->until)
1570 >          conf_free(conf);
1571        }
1572 +      else
1573 +        conf_free(conf);
1574      }
1575    }
1576  
1577    /*
1578     * don't delete the class table, rather mark all entries
1579 <   * for deletion. The table is cleaned up by check_class. - avalon
1579 >   * for deletion. The table is cleaned up by class_delete_marked. - avalon
1580     */
1581 <  DLINK_FOREACH(ptr, class_items.head)
2540 <  {
2541 <    cltmp = map_to_conf(ptr->data);
2542 <
2543 <    if (ptr != class_items.tail)  /* never mark the "default" class */
2544 <      cltmp->active = 0;
2545 <  }
1581 >  class_mark_for_deletion();
1582  
1583    clear_out_address_conf();
1584  
# Line 2578 | Line 1614 | clear_out_old_conf(void)
1614                                                 SSL_OP_NO_TLSv1);
1615   #endif
1616  
2581  /* clean out old resvs from the conf */
2582  clear_conf_resv();
2583
1617    /* clean out AdminInfo */
1618    MyFree(AdminInfo.name);
1619    AdminInfo.name = NULL;
# Line 2589 | Line 1622 | clear_out_old_conf(void)
1622    MyFree(AdminInfo.description);
1623    AdminInfo.description = NULL;
1624  
2592  /* operator{} and class{} blocks are freed above */
1625    /* clean out listeners */
1626    close_listeners();
1627  
2596  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2597   * exempt{} and gecos{} blocks are freed above too
2598   */
2599
1628    /* clean out general */
1629    MyFree(ConfigFileEntry.service_name);
1630    ConfigFileEntry.service_name = NULL;
# Line 2605 | Line 1633 | clear_out_old_conf(void)
1633    delete_isupport("EXCEPTS");
1634   }
1635  
2608 /* flush_deleted_I_P()
2609 *
2610 * inputs       - none
2611 * output       - none
2612 * side effects - This function removes I/P conf items
2613 */
2614 static void
2615 flush_deleted_I_P(void)
2616 {
2617  dlink_node *ptr;
2618  dlink_node *next_ptr;
2619  struct ConfItem *conf;
2620  struct AccessItem *aconf;
2621  dlink_list * free_items [] = {
2622    &server_items, &oconf_items, NULL
2623  };
2624  dlink_list ** iterator = free_items; /* C is dumb */
2625
2626  /* flush out deleted I and P lines
2627   * although still in use.
2628   */
2629  for (; *iterator != NULL; iterator++)
2630  {
2631    DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2632    {
2633      conf = ptr->data;
2634      aconf = (struct AccessItem *)map_to_conf(conf);
2635
2636      if (IsConfIllegal(aconf))
2637      {
2638        dlinkDelete(ptr, *iterator);
2639
2640        if (aconf->clients == 0)
2641          delete_conf_item(conf);
2642      }
2643    }
2644  }
2645 }
2646
2647 /* get_conf_name()
2648 *
2649 * inputs       - type of conf file to return name of file for
2650 * output       - pointer to filename for type of conf
2651 * side effects - none
2652 */
2653 const char *
2654 get_conf_name(ConfType type)
2655 {
2656  switch (type)
2657  {
2658    case CONF_TYPE:
2659      return ConfigFileEntry.configfile;
2660      break;
2661    case KLINE_TYPE:
2662      return ConfigFileEntry.klinefile;
2663      break;
2664    case RKLINE_TYPE:
2665      return ConfigFileEntry.rklinefile;
2666      break;
2667    case DLINE_TYPE:
2668      return ConfigFileEntry.dlinefile;
2669      break;
2670    case XLINE_TYPE:
2671      return ConfigFileEntry.xlinefile;
2672      break;
2673    case RXLINE_TYPE:
2674      return ConfigFileEntry.rxlinefile;
2675      break;
2676    case CRESV_TYPE:
2677      return ConfigFileEntry.cresvfile;
2678      break;
2679    case NRESV_TYPE:
2680      return ConfigFileEntry.nresvfile;
2681      break;
2682    case GLINE_TYPE:
2683      return ConfigFileEntry.glinefile;
2684      break;
2685
2686    default:
2687      return NULL;  /* This should NEVER HAPPEN since we call this function
2688                       only with the above values, this will cause us to core
2689                       at some point if this happens so we know where it was */
2690  }
2691 }
2692
2693 #define BAD_PING (-1)
2694
2695 /* get_conf_ping()
2696 *
2697 * inputs       - pointer to struct AccessItem
2698 *              - pointer to a variable that receives ping warning time
2699 * output       - ping frequency
2700 * side effects - NONE
2701 */
2702 static int
2703 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2704 {
2705  struct ClassItem *aclass;
2706  struct AccessItem *aconf;
2707
2708  if (conf != NULL)
2709  {
2710    aconf = (struct AccessItem *)map_to_conf(conf);
2711    if (aconf->class_ptr != NULL)
2712    {
2713      aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2714      *pingwarn = aclass->ping_warning;
2715      return aclass->ping_freq;
2716    }
2717  }
2718
2719  return BAD_PING;
2720 }
2721
2722 /* get_client_class()
2723 *
2724 * inputs       - pointer to client struct
2725 * output       - pointer to name of class
2726 * side effects - NONE
2727 */
2728 const char *
2729 get_client_class(struct Client *target_p)
2730 {
2731  dlink_node *ptr;
2732  struct ConfItem *conf;
2733  struct AccessItem *aconf;
2734
2735  if (target_p != NULL && !IsMe(target_p) &&
2736      target_p->localClient->confs.head != NULL)
2737  {
2738    DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2739    {
2740      conf = ptr->data;
2741
2742      if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2743          conf->type == OPER_TYPE)
2744      {
2745        aconf = (struct AccessItem *) map_to_conf(conf);
2746        if (aconf->class_ptr != NULL)
2747          return aconf->class_ptr->name;
2748      }
2749    }
2750  }
2751
2752  return "default";
2753 }
2754
2755 /* get_client_ping()
2756 *
2757 * inputs       - pointer to client struct
2758 *              - pointer to a variable that receives ping warning time
2759 * output       - ping frequency
2760 * side effects - NONE
2761 */
2762 int
2763 get_client_ping(struct Client *target_p, int *pingwarn)
2764 {
2765  int ping;
2766  struct ConfItem *conf;
2767  dlink_node *nlink;
2768
2769  if (target_p->localClient->confs.head != NULL)
2770    DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2771    {
2772      conf = nlink->data;
2773
2774      if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2775          (conf->type == OPER_TYPE))
2776      {
2777        ping = get_conf_ping(conf, pingwarn);
2778        if (ping > 0)
2779          return ping;
2780      }
2781    }
2782
2783  *pingwarn = 0;
2784  return DEFAULT_PINGFREQUENCY;
2785 }
2786
2787 /* find_class()
2788 *
2789 * inputs       - string name of class
2790 * output       - corresponding Class pointer
2791 * side effects - NONE
2792 */
2793 struct ConfItem *
2794 find_class(const char *classname)
2795 {
2796  struct ConfItem *conf;
2797
2798  if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2799    return conf;
2800
2801  return class_default;
2802 }
2803
2804 /* check_class()
2805 *
2806 * inputs       - NONE
2807 * output       - NONE
2808 * side effects -
2809 */
2810 void
2811 check_class(void)
2812 {
2813  dlink_node *ptr = NULL, *next_ptr = NULL;
2814
2815  DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2816  {
2817    struct ClassItem *aclass = map_to_conf(ptr->data);
2818
2819    if (!aclass->active && !aclass->curr_user_count)
2820    {
2821      destroy_cidr_class(aclass);
2822      delete_conf_item(ptr->data);
2823    }
2824  }
2825 }
2826
2827 /* init_class()
2828 *
2829 * inputs       - NONE
2830 * output       - NONE
2831 * side effects -
2832 */
2833 void
2834 init_class(void)
2835 {
2836  struct ClassItem *aclass;
2837
2838  class_default = make_conf_item(CLASS_TYPE);
2839
2840  aclass = map_to_conf(class_default);
2841  aclass->active = 1;
2842  DupString(class_default->name, "default");
2843  aclass->con_freq  = DEFAULT_CONNECTFREQUENCY;
2844  aclass->ping_freq = DEFAULT_PINGFREQUENCY;
2845  aclass->max_total = MAXIMUM_LINKS_DEFAULT;
2846  aclass->max_sendq = DEFAULT_SENDQ;
2847
2848  client_check_cb = register_callback("check_client", check_client);
2849 }
2850
2851 /* get_sendq()
2852 *
2853 * inputs       - pointer to client
2854 * output       - sendq for this client as found from its class
2855 * side effects - NONE
2856 */
2857 unsigned int
2858 get_sendq(struct Client *client_p)
2859 {
2860  unsigned int sendq = DEFAULT_SENDQ;
2861  dlink_node *ptr;
2862  struct ConfItem *conf;
2863  struct ConfItem *class_conf;
2864  struct ClassItem *aclass;
2865  struct AccessItem *aconf;
2866
2867  if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2868  {
2869    DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2870    {
2871      conf = ptr->data;
2872      if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2873          || (conf->type == CLIENT_TYPE))
2874      {
2875        aconf = (struct AccessItem *)map_to_conf(conf);
2876        if ((class_conf = aconf->class_ptr) == NULL)
2877          continue;
2878        aclass = (struct ClassItem *)map_to_conf(class_conf);
2879        sendq = aclass->max_sendq;
2880        return sendq;
2881      }
2882    }
2883  }
2884  /* XXX return a default?
2885   * if here, then there wasn't an attached conf with a sendq
2886   * that is very bad -Dianora
2887   */
2888  return DEFAULT_SENDQ;
2889 }
2890
1636   /* conf_add_class_to_conf()
1637   *
1638   * inputs       - pointer to config item
# Line 2895 | Line 1640 | get_sendq(struct Client *client_p)
1640   * side effects - Add a class pointer to a conf
1641   */
1642   void
1643 < conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
1643 > conf_add_class_to_conf(struct MaskItem *conf, const char *class_name)
1644   {
2900  struct AccessItem *aconf = map_to_conf(conf);
2901  struct ClassItem *class = NULL;
2902
1645    if (class_name == NULL)
1646    {
1647 <    aconf->class_ptr = class_default;
1647 >    conf->class = class_default;
1648  
1649 <    if (conf->type == CLIENT_TYPE)
1650 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1649 >    if (conf->type == CONF_CLIENT)
1650 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1651                             "Warning *** Defaulting to default class for %s@%s",
1652 <                           aconf->user, aconf->host);
1652 >                           conf->user, conf->host);
1653      else
1654 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1654 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1655                             "Warning *** Defaulting to default class for %s",
1656                             conf->name);
1657    }
1658    else
1659 <    aconf->class_ptr = find_class(class_name);
2918 <
2919 <  if (aconf->class_ptr)
2920 <    class = map_to_conf(aconf->class_ptr);
1659 >    conf->class = class_find(class_name, 1);
1660  
1661 <  if (aconf->class_ptr == NULL || !class->active)
1661 >  if (conf->class == NULL)
1662    {
1663 <    if (conf->type == CLIENT_TYPE)
1664 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1663 >    if (conf->type == CONF_CLIENT)
1664 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1665                             "Warning *** Defaulting to default class for %s@%s",
1666 <                           aconf->user, aconf->host);
1666 >                           conf->user, conf->host);
1667      else
1668 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1668 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1669                             "Warning *** Defaulting to default class for %s",
1670                             conf->name);
1671 <    aconf->class_ptr = class_default;
1671 >    conf->class = class_default;
1672    }
1673   }
1674  
2936 /* conf_add_server()
2937 *
2938 * inputs       - pointer to config item
2939 *              - pointer to link count already on this conf
2940 * output       - NONE
2941 * side effects - Add a connect block
2942 */
2943 int
2944 conf_add_server(struct ConfItem *conf, const char *class_name)
2945 {
2946  struct AccessItem *aconf = map_to_conf(conf);
2947
2948  conf_add_class_to_conf(conf, class_name);
2949
2950  if (!aconf->host || !conf->name)
2951  {
2952    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
2953    ilog(LOG_TYPE_IRCD, "Bad connect block");
2954    return -1;
2955  }
2956
2957  if (EmptyString(aconf->passwd))
2958  {
2959    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
2960                         conf->name);
2961    ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
2962    return -1;
2963  }
2964
2965  lookup_confhost(conf);
2966
2967  return 0;
2968 }
2969
1675   /* yyerror()
1676   *
1677   * inputs       - message from parser
# Line 2982 | Line 1687 | yyerror(const char *msg)
1687      return;
1688  
1689    strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1690 <  sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
1690 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1691 >                       "\"%s\", line %u: %s: %s",
1692 >                       conffilebuf, lineno + 1, msg, newlinebuf);
1693 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1694 >       conffilebuf, lineno + 1, msg, newlinebuf);
1695 > }
1696 >
1697 > void
1698 > conf_error_report(const char *msg)
1699 > {
1700 >  char newlinebuf[IRCD_BUFSIZE];
1701 >
1702 >  strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1703 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1704 >                       "\"%s\", line %u: %s: %s",
1705                         conffilebuf, lineno + 1, msg, newlinebuf);
1706    ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1707         conffilebuf, lineno + 1, msg, newlinebuf);
# Line 3035 | Line 1754 | valid_tkline(const char *p, int minutes)
1754    return result;
1755   }
1756  
1757 + /* valid_wild_card_simple()
1758 + *
1759 + * inputs       - data to check for sufficient non-wildcard characters
1760 + * outputs      - 1 if valid, else 0
1761 + * side effects - none
1762 + */
1763 + int
1764 + valid_wild_card_simple(const char *data)
1765 + {
1766 +  const unsigned char *p = (const unsigned char *)data;
1767 +  unsigned char tmpch = '\0';
1768 +  int nonwild = 0;
1769 +
1770 +  while ((tmpch = *p++))
1771 +  {
1772 +    if (tmpch == '\\')
1773 +    {
1774 +      ++p;
1775 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1776 +        return 1;
1777 +    }
1778 +    else if (!IsMWildChar(tmpch))
1779 +    {
1780 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1781 +        return 1;
1782 +    }
1783 +  }
1784 +
1785 +  return 0;
1786 + }
1787 +
1788   /* valid_wild_card()
1789   *
1790   * input        - pointer to client
# Line 3046 | Line 1796 | valid_tkline(const char *p, int minutes)
1796   int
1797   valid_wild_card(struct Client *source_p, int warn, int count, ...)
1798   {
3049  char *p;
1799    char tmpch;
1800    int nonwild = 0;
1801    va_list args;
# Line 3067 | Line 1816 | valid_wild_card(struct Client *source_p,
1816  
1817    while (count--)
1818    {
1819 <    p = va_arg(args, char *);
1819 >    const char *p = va_arg(args, const char *);
1820      if (p == NULL)
1821        continue;
1822  
# Line 3293 | Line 2042 | find_user_host(struct Client *source_p,
2042      
2043      return 1;
2044    }
2045 <  else if (!(flags & NOUSERLOOKUP))
2045 >  else
2046    {
2047      /* Try to find user@host mask from nick */
2048      /* Okay to use source_p as the first param, because source_p == client_p */
# Line 3341 | Line 2090 | find_user_host(struct Client *source_p,
2090   int
2091   valid_comment(struct Client *source_p, char *comment, int warn)
2092   {
3344  if (strchr(comment, '"'))
3345  {
3346    if (warn)
3347      sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3348                 me.name, source_p->name);
3349    return 0;
3350  }
3351
2093    if (strlen(comment) > REASONLEN)
2094      comment[REASONLEN-1] = '\0';
2095  
# Line 3363 | Line 2104 | valid_comment(struct Client *source_p, c
2104   * side effects - none
2105   */
2106   int
2107 < match_conf_password(const char *password, const struct AccessItem *aconf)
2107 > match_conf_password(const char *password, const struct MaskItem *conf)
2108   {
2109    const char *encr = NULL;
2110  
2111 <  if (password == NULL || aconf->passwd == NULL)
2111 >  if (EmptyString(password) || EmptyString(conf->passwd))
2112      return 0;
2113  
2114 <  if (aconf->flags & CONF_FLAGS_ENCRYPTED)
2115 <  {
3375 <    /* use first two chars of the password they send in as salt */
3376 <    /* If the password in the conf is MD5, and ircd is linked
3377 <     * to scrypt on FreeBSD, or the standard crypt library on
3378 <     * glibc Linux, then this code will work fine on generating
3379 <     * the proper encrypted hash for comparison.
3380 <     */
3381 <    if (*aconf->passwd)
3382 <      encr = crypt(password, aconf->passwd);
3383 <    else
3384 <      encr = "";
3385 <  }
2114 >  if (conf->flags & CONF_FLAGS_ENCRYPTED)
2115 >    encr = crypt(password, conf->passwd);
2116    else
2117      encr = password;
2118  
2119 <  return !strcmp(encr, aconf->passwd);
2119 >  return !strcmp(encr, conf->passwd);
2120   }
2121  
2122   /*
# Line 3415 | Line 2145 | cluster_a_line(struct Client *source_p,
2145  
2146    DLINK_FOREACH(ptr, cluster_items.head)
2147    {
2148 <    const struct ConfItem *conf = ptr->data;
2148 >    const struct MaskItem *conf = ptr->data;
2149  
2150      if (conf->flags & cluster_type)
2151        sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
# Line 3509 | Line 2239 | split_nuh(struct split_nuh_item *const i
2239      }
2240    }
2241   }
3512
3513 /*
3514 * flags_to_ascii
3515 *
3516 * inputs       - flags is a bitmask
3517 *              - pointer to table of ascii letters corresponding
3518 *                to each bit
3519 *              - flag 1 for convert ToLower if bit missing
3520 *                0 if ignore.
3521 * output       - none
3522 * side effects - string pointed to by p has bitmap chars written to it
3523 */
3524 static void
3525 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3526               int lowerit)
3527 {
3528  unsigned int mask = 1;
3529  int i = 0;
3530
3531  for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3532  {
3533    if (flags & mask)
3534      *p++ = bit_table[i];
3535    else if (lowerit)
3536      *p++ = ToLower(bit_table[i]);
3537  }
3538  *p = '\0';
3539 }
3540
3541 /*
3542 * cidr_limit_reached
3543 *
3544 * inputs       - int flag allowing over_rule of limits
3545 *              - pointer to the ip to be added
3546 *              - pointer to the class
3547 * output       - non zero if limit reached
3548 *                0 if limit not reached
3549 * side effects -
3550 */
3551 static int
3552 cidr_limit_reached(int over_rule,
3553                   struct irc_ssaddr *ip, struct ClassItem *aclass)
3554 {
3555  dlink_node *ptr = NULL;
3556  struct CidrItem *cidr;
3557
3558  if (aclass->number_per_cidr <= 0)
3559    return 0;
3560
3561  if (ip->ss.ss_family == AF_INET)
3562  {
3563    if (aclass->cidr_bitlen_ipv4 <= 0)
3564      return 0;
3565
3566    DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3567    {
3568      cidr = ptr->data;
3569      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3570      {
3571        if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3572          return -1;
3573        cidr->number_on_this_cidr++;
3574        return 0;
3575      }
3576    }
3577    cidr = MyMalloc(sizeof(struct CidrItem));
3578    cidr->number_on_this_cidr = 1;
3579    cidr->mask = *ip;
3580    mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv4);
3581    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3582  }
3583 #ifdef IPV6
3584  else if (aclass->cidr_bitlen_ipv6 > 0)
3585  {
3586    DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3587    {
3588      cidr = ptr->data;
3589      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3590      {
3591        if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3592          return -1;
3593        cidr->number_on_this_cidr++;
3594        return 0;
3595      }
3596    }
3597    cidr = MyMalloc(sizeof(struct CidrItem));
3598    cidr->number_on_this_cidr = 1;
3599    cidr->mask = *ip;
3600    mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv6);
3601    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3602  }
3603 #endif
3604  return 0;
3605 }
3606
3607 /*
3608 * remove_from_cidr_check
3609 *
3610 * inputs       - pointer to the ip to be removed
3611 *              - pointer to the class
3612 * output       - NONE
3613 * side effects -
3614 */
3615 static void
3616 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3617 {
3618  dlink_node *ptr = NULL;
3619  dlink_node *next_ptr = NULL;
3620  struct CidrItem *cidr;
3621
3622  if (aclass->number_per_cidr == 0)
3623    return;
3624
3625  if (ip->ss.ss_family == AF_INET)
3626  {
3627    if (aclass->cidr_bitlen_ipv4 <= 0)
3628      return;
3629
3630    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3631    {
3632      cidr = ptr->data;
3633      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3634      {
3635        cidr->number_on_this_cidr--;
3636        if (cidr->number_on_this_cidr == 0)
3637        {
3638          dlinkDelete(ptr, &aclass->list_ipv4);
3639          MyFree(cidr);
3640          return;
3641        }
3642      }
3643    }
3644  }
3645 #ifdef IPV6
3646  else if (aclass->cidr_bitlen_ipv6 > 0)
3647  {
3648    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3649    {
3650      cidr = ptr->data;
3651      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3652      {
3653        cidr->number_on_this_cidr--;
3654        if (cidr->number_on_this_cidr == 0)
3655        {
3656          dlinkDelete(ptr, &aclass->list_ipv6);
3657          MyFree(cidr);
3658          return;
3659        }
3660      }
3661    }
3662  }
3663 #endif
3664 }
3665
3666 static void
3667 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3668                  dlink_list *old_list, dlink_list *new_list, int changed)
3669 {
3670  dlink_node *ptr;
3671  struct Client *client_p;
3672  struct ConfItem *conf;
3673  struct AccessItem *aconf;
3674
3675  if (!changed)
3676  {
3677    *new_list = *old_list;
3678    old_list->head = old_list->tail = NULL;
3679    old_list->length = 0;
3680    return;
3681  }
3682
3683  DLINK_FOREACH(ptr, local_client_list.head)
3684  {
3685    client_p = ptr->data;
3686    if (client_p->localClient->aftype != aftype)
3687      continue;
3688    if (dlink_list_length(&client_p->localClient->confs) == 0)
3689      continue;
3690
3691    conf = client_p->localClient->confs.tail->data;
3692    if (conf->type == CLIENT_TYPE)
3693    {
3694      aconf = map_to_conf(conf);
3695      if (aconf->class_ptr == oldcl)
3696        cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3697    }
3698  }
3699 }
3700
3701 /*
3702 * rebuild_cidr_class
3703 *
3704 * inputs       - pointer to old conf
3705 *              - pointer to new_class
3706 * output       - none
3707 * side effects - rebuilds the class link list of cidr blocks
3708 */
3709 void
3710 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3711 {
3712  struct ClassItem *old_class = map_to_conf(conf);
3713
3714  if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
3715  {
3716    if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
3717      rebuild_cidr_list(AF_INET, conf, new_class,
3718                        &old_class->list_ipv4, &new_class->list_ipv4,
3719                        old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
3720
3721 #ifdef IPV6
3722    if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
3723      rebuild_cidr_list(AF_INET6, conf, new_class,
3724                        &old_class->list_ipv6, &new_class->list_ipv6,
3725                        old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
3726 #endif
3727  }
3728
3729  destroy_cidr_class(old_class);
3730 }
3731
3732 /*
3733 * destroy_cidr_list
3734 *
3735 * inputs       - pointer to class dlink list of cidr blocks
3736 * output       - none
3737 * side effects - completely destroys the class link list of cidr blocks
3738 */
3739 static void
3740 destroy_cidr_list(dlink_list *list)
3741 {
3742  dlink_node *ptr = NULL, *next_ptr = NULL;
3743
3744  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3745  {
3746    dlinkDelete(ptr, list);
3747    MyFree(ptr->data);
3748  }
3749 }
3750
3751 /*
3752 * destroy_cidr_class
3753 *
3754 * inputs       - pointer to class
3755 * output       - none
3756 * side effects - completely destroys the class link list of cidr blocks
3757 */
3758 static void
3759 destroy_cidr_class(struct ClassItem *aclass)
3760 {
3761  destroy_cidr_list(&aclass->list_ipv4);
3762  destroy_cidr_list(&aclass->list_ipv6);
3763 }

Diff Legend

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