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 1353 by michael, Sun Apr 15 18:35:55 2012 UTC vs.
ircd-hybrid/trunk/src/conf.c (file contents), Revision 2283 by michael, Tue Jun 18 19:13:20 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"
31   #include "channel.h"
32   #include "client.h"
33   #include "event.h"
35 #include "hash.h"
34   #include "hook.h"
35   #include "irc_string.h"
38 #include "sprintf_irc.h"
36   #include "s_bsd.h"
37   #include "ircd.h"
38   #include "listener.h"
# Line 47 | Line 44
44   #include "send.h"
45   #include "s_gline.h"
46   #include "memory.h"
47 + #include "mempool.h"
48   #include "irc_res.h"
49   #include "userhost.h"
50   #include "s_user.h"
51   #include "channel_mode.h"
52   #include "parse.h"
53   #include "s_misc.h"
54 + #include "conf_db.h"
55 + #include "conf_class.h"
56 + #include "motd.h"
57  
57 struct Callback *client_check_cb = NULL;
58   struct config_server_hide ConfigServerHide;
59  
60   /* general conf items link list root, other than k lines etc. */
61   dlink_list service_items = { NULL, NULL, 0 };
62   dlink_list server_items  = { NULL, NULL, 0 };
63   dlink_list cluster_items = { NULL, NULL, 0 };
64 dlink_list hub_items     = { NULL, NULL, 0 };
65 dlink_list leaf_items    = { NULL, NULL, 0 };
64   dlink_list oconf_items   = { NULL, NULL, 0 };
65   dlink_list uconf_items   = { NULL, NULL, 0 };
66   dlink_list xconf_items   = { NULL, NULL, 0 };
69 dlink_list rxconf_items  = { NULL, NULL, 0 };
70 dlink_list rkconf_items  = { NULL, NULL, 0 };
67   dlink_list nresv_items   = { NULL, NULL, 0 };
68 < dlink_list class_items   = { NULL, NULL, 0 };
73 < dlink_list gdeny_items   = { NULL, NULL, 0 };
74 <
75 < dlink_list temporary_klines  = { NULL, NULL, 0 };
76 < dlink_list temporary_dlines  = { NULL, NULL, 0 };
77 < dlink_list temporary_xlines  = { NULL, NULL, 0 };
78 < dlink_list temporary_rklines = { NULL, NULL, 0 };
79 < dlink_list temporary_glines  = { NULL, NULL, 0 };
80 < dlink_list temporary_rxlines = { NULL, NULL, 0 };
81 < dlink_list temporary_resv = { NULL, NULL, 0 };
68 > dlink_list cresv_items = { NULL, NULL, 0 };
69  
70   extern unsigned int lineno;
71   extern char linebuf[];
72   extern char conffilebuf[IRCD_BUFSIZE];
86 extern char yytext[];
73   extern int yyparse(); /* defined in y.tab.c */
74  
75   struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
76  
77   /* internally defined functions */
92 static void lookup_confhost(struct ConfItem *);
93 static void set_default_conf(void);
94 static void validate_conf(void);
78   static void read_conf(FILE *);
79   static void clear_out_old_conf(void);
97 static void flush_deleted_I_P(void);
80   static void expire_tklines(dlink_list *);
81   static void garbage_collect_ip_entries(void);
82   static int hash_ip(struct irc_ssaddr *);
83 < static int verify_access(struct Client *, const char *);
84 < static int attach_iline(struct Client *, struct ConfItem *);
83 > static int verify_access(struct Client *);
84 > static int attach_iline(struct Client *, struct MaskItem *);
85   static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
86 < static void parse_conf_file(int, int);
105 < static dlink_list *map_to_list(ConfType);
106 < static struct AccessItem *find_regexp_kline(const char *[]);
86 > static dlink_list *map_to_list(enum maskitem_type);
87   static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
88  
109 /*
110 * bit_len
111 */
112 static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
113 static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
114 static void destroy_cidr_class(struct ClassItem *);
115
116 static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
117
118 /* address of default class conf */
119 static struct ConfItem *class_default;
89  
90   /* usually, with hash tables, you use a prime number...
91   * but in this case I am dealing with ip addresses,
# Line 127 | Line 96 | static struct ConfItem *class_default;
96   struct ip_entry
97   {
98    struct irc_ssaddr ip;
99 <  int count;
99 >  unsigned int count;
100    time_t last_attempt;
101    struct ip_entry *next;
102   };
103  
104   static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
105 < static BlockHeap *ip_entry_heap = NULL;
105 > static mp_pool_t *ip_entry_pool = NULL;
106   static int ip_entries_count = 0;
107  
108  
140 void *
141 map_to_conf(struct ConfItem *aconf)
142 {
143  void *conf;
144  conf = (void *)((uintptr_t)aconf +
145                  (uintptr_t)sizeof(struct ConfItem));
146  return(conf);
147 }
148
149 struct ConfItem *
150 unmap_conf_item(void *aconf)
151 {
152  struct ConfItem *conf;
153
154  conf = (struct ConfItem *)((uintptr_t)aconf -
155                             (uintptr_t)sizeof(struct ConfItem));
156  return(conf);
157 }
158
109   /* conf_dns_callback()
110   *
111 < * inputs       - pointer to struct AccessItem
111 > * inputs       - pointer to struct MaskItem
112   *              - pointer to DNSReply reply
113   * output       - none
114   * side effects - called when resolver query finishes
# Line 169 | Line 119 | unmap_conf_item(void *aconf)
119   static void
120   conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
121   {
122 <  struct AccessItem *aconf = vptr;
122 >  struct MaskItem *conf = vptr;
123  
124 <  aconf->dns_pending = 0;
124 >  conf->dns_pending = 0;
125  
126    if (addr != NULL)
127 <    memcpy(&aconf->ipnum, addr, sizeof(aconf->ipnum));
127 >    memcpy(&conf->addr, addr, sizeof(conf->addr));
128    else
129 <    aconf->dns_failed = 1;
129 >    conf->dns_failed = 1;
130   }
131  
132   /* conf_dns_lookup()
# Line 186 | Line 136 | conf_dns_callback(void *vptr, const stru
136   * allocate a dns_query and start ns lookup.
137   */
138   static void
139 < conf_dns_lookup(struct AccessItem *aconf)
139 > conf_dns_lookup(struct MaskItem *conf)
140   {
141 <  if (!aconf->dns_pending)
141 >  if (!conf->dns_pending)
142    {
143 <    aconf->dns_pending = 1;
144 <    gethost_byname(conf_dns_callback, aconf, aconf->host);
143 >    conf->dns_pending = 1;
144 >    gethost_byname(conf_dns_callback, conf, conf->host);
145    }
146   }
147  
148 < /* make_conf_item()
149 < *
200 < * inputs       - type of item
201 < * output       - pointer to new conf entry
202 < * side effects - none
203 < */
204 < struct ConfItem *
205 < make_conf_item(ConfType type)
148 > struct MaskItem *
149 > conf_make(enum maskitem_type type)
150   {
151 <  struct ConfItem *conf = NULL;
152 <  struct AccessItem *aconf = NULL;
209 <  struct ClassItem *aclass = NULL;
210 <  int status = 0;
211 <
212 <  switch (type)
213 <  {
214 <  case DLINE_TYPE:
215 <  case EXEMPTDLINE_TYPE:
216 <  case GLINE_TYPE:
217 <  case KLINE_TYPE:
218 <  case CLIENT_TYPE:
219 <  case OPER_TYPE:
220 <  case SERVER_TYPE:
221 <    conf = MyMalloc(sizeof(struct ConfItem) +
222 <                    sizeof(struct AccessItem));
223 <    aconf = map_to_conf(conf);
224 <    aconf->aftype = AF_INET;
225 <
226 <    /* Yes, sigh. switch on type again */
227 <    switch (type)
228 <    {
229 <    case EXEMPTDLINE_TYPE:
230 <      status = CONF_EXEMPTDLINE;
231 <      break;
232 <
233 <    case DLINE_TYPE:
234 <      status = CONF_DLINE;
235 <      break;
236 <
237 <    case KLINE_TYPE:
238 <      status = CONF_KLINE;
239 <      break;
240 <
241 <    case GLINE_TYPE:
242 <      status = CONF_GLINE;
243 <      break;
244 <
245 <    case CLIENT_TYPE:
246 <      status = CONF_CLIENT;
247 <      break;
248 <
249 <    case OPER_TYPE:
250 <      status = CONF_OPERATOR;
251 <      dlinkAdd(conf, &conf->node, &oconf_items);
252 <      break;
253 <
254 <    case SERVER_TYPE:
255 <      status = CONF_SERVER;
256 <      dlinkAdd(conf, &conf->node, &server_items);
257 <      break;
258 <
259 <    default:
260 <      break;
261 <    }
262 <    aconf->status = status;
263 <    break;
264 <
265 <  case LEAF_TYPE:
266 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
267 <                                       sizeof(struct MatchItem));
268 <    dlinkAdd(conf, &conf->node, &leaf_items);
269 <    break;
151 >  struct MaskItem *conf = MyMalloc(sizeof(*conf));
152 >  dlink_list *list = NULL;
153  
154 <  case HUB_TYPE:
155 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
156 <                                       sizeof(struct MatchItem));
274 <    dlinkAdd(conf, &conf->node, &hub_items);
275 <    break;
276 <
277 <  case ULINE_TYPE:
278 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
279 <                                       sizeof(struct MatchItem));
280 <    dlinkAdd(conf, &conf->node, &uconf_items);
281 <    break;
282 <
283 <  case GDENY_TYPE:
284 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
285 <                                       sizeof(struct AccessItem));
286 <    dlinkAdd(conf, &conf->node, &gdeny_items);
287 <    break;
288 <
289 <  case XLINE_TYPE:
290 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
291 <                                       sizeof(struct MatchItem));
292 <    dlinkAdd(conf, &conf->node, &xconf_items);
293 <    break;
294 < #ifdef HAVE_LIBPCRE
295 <  case RXLINE_TYPE:
296 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
297 <                                       sizeof(struct MatchItem));
298 <    dlinkAdd(conf, &conf->node, &rxconf_items);
299 <    break;
300 <
301 <  case RKLINE_TYPE:
302 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
303 <                                       sizeof(struct AccessItem));
304 <    aconf = map_to_conf(conf);
305 <    aconf->status = CONF_KLINE;
306 <    dlinkAdd(conf, &conf->node, &rkconf_items);
307 <    break;
308 < #endif
309 <  case CLUSTER_TYPE:
310 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
311 <    dlinkAdd(conf, &conf->node, &cluster_items);
312 <    break;
313 <
314 <  case CRESV_TYPE:
315 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
316 <                                       sizeof(struct ResvChannel));
317 <    break;
318 <
319 <  case NRESV_TYPE:
320 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
321 <                                       sizeof(struct MatchItem));
322 <    dlinkAdd(conf, &conf->node, &nresv_items);
323 <    break;
324 <
325 <  case SERVICE_TYPE:
326 <    status = CONF_SERVICE;
327 <    conf = MyMalloc(sizeof(struct ConfItem));
328 <    dlinkAdd(conf, &conf->node, &service_items);
329 <    break;
330 <
331 <  case CLASS_TYPE:
332 <    conf = MyMalloc(sizeof(struct ConfItem) +
333 <                           sizeof(struct ClassItem));
334 <    dlinkAdd(conf, &conf->node, &class_items);
335 <
336 <    aclass = map_to_conf(conf);
337 <    aclass->active = 1;
338 <    ConFreq(aclass) = DEFAULT_CONNECTFREQUENCY;
339 <    PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
340 <    MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
341 <    MaxSendq(aclass) = DEFAULT_SENDQ;
342 <
343 <    break;
344 <
345 <  default:
346 <    conf = NULL;
347 <    break;
348 <  }
349 <
350 <  /* XXX Yes, this will core if default is hit. I want it to for now - db */
351 <  conf->type = type;
154 >  conf->type   = type;
155 >  conf->active = 1;
156 >  conf->aftype = AF_INET;
157  
158 +  if ((list = map_to_list(type)))
159 +    dlinkAdd(conf, &conf->node, list);
160    return conf;
161   }
162  
163   void
164 < delete_conf_item(struct ConfItem *conf)
164 > conf_free(struct MaskItem *conf)
165   {
166 <  dlink_node *m = NULL;
167 <  struct MatchItem *match_item;
168 <  struct AccessItem *aconf;
169 <  ConfType type = conf->type;
166 >  dlink_node *ptr = NULL, *ptr_next = NULL;
167 >  dlink_list *list = NULL;
168 >
169 >  if (conf->node.next)
170 >    if ((list = map_to_list(conf->type)))
171 >      dlinkDelete(&conf->node, list);
172  
173    MyFree(conf->name);
365  conf->name = NULL;
174  
175 <  switch(type)
176 <  {
177 <  case DLINE_TYPE:
178 <  case EXEMPTDLINE_TYPE:
179 <  case GLINE_TYPE:
180 <  case KLINE_TYPE:
181 <  case CLIENT_TYPE:
182 <  case OPER_TYPE:
183 <  case SERVER_TYPE:
184 <    aconf = map_to_conf(conf);
185 <
186 <    if (aconf->dns_pending)
187 <      delete_resolver_queries(aconf);
188 <    if (aconf->passwd != NULL)
189 <      memset(aconf->passwd, 0, strlen(aconf->passwd));
382 <    if (aconf->spasswd != NULL)
383 <      memset(aconf->spasswd, 0, strlen(aconf->spasswd));
384 <    aconf->class_ptr = NULL;
385 <
386 <    MyFree(aconf->passwd);
387 <    MyFree(aconf->spasswd);
388 <    MyFree(aconf->reason);
389 <    MyFree(aconf->oper_reason);
390 <    MyFree(aconf->user);
391 <    MyFree(aconf->host);
392 <    MyFree(aconf->cipher_list);
175 >  if (conf->dns_pending)
176 >    delete_resolver_queries(conf);
177 >  if (conf->passwd != NULL)
178 >    memset(conf->passwd, 0, strlen(conf->passwd));
179 >  if (conf->spasswd != NULL)
180 >    memset(conf->spasswd, 0, strlen(conf->spasswd));
181 >
182 >  conf->class = NULL;
183 >
184 >  MyFree(conf->passwd);
185 >  MyFree(conf->spasswd);
186 >  MyFree(conf->reason);
187 >  MyFree(conf->certfp);
188 >  MyFree(conf->user);
189 >  MyFree(conf->host);
190   #ifdef HAVE_LIBCRYPTO
191 <    if (aconf->rsa_public_key)
395 <      RSA_free(aconf->rsa_public_key);
396 <    MyFree(aconf->rsa_public_key_file);
397 < #endif
398 <
399 <    /* Yes, sigh. switch on type again */
400 <    switch(type)
401 <    {
402 <    case EXEMPTDLINE_TYPE:
403 <    case DLINE_TYPE:
404 <    case GLINE_TYPE:
405 <    case KLINE_TYPE:
406 <    case CLIENT_TYPE:
407 <      MyFree(conf);
408 <      break;
191 >  MyFree(conf->cipher_list);
192  
193 <    case OPER_TYPE:
194 <      aconf = map_to_conf(conf);
412 <      if (!IsConfIllegal(aconf))
413 <        dlinkDelete(&conf->node, &oconf_items);
414 <      MyFree(conf);
415 <      break;
416 <
417 <    case SERVER_TYPE:
418 <      aconf = map_to_conf(conf);
419 <      if (!IsConfIllegal(aconf))
420 <        dlinkDelete(&conf->node, &server_items);
421 <      MyFree(conf);
422 <      break;
423 <
424 <    default:
425 <      break;
426 <    }
427 <    break;
428 <
429 <  case HUB_TYPE:
430 <    match_item = map_to_conf(conf);
431 <    MyFree(match_item->user);
432 <    MyFree(match_item->host);
433 <    MyFree(match_item->reason);
434 <    MyFree(match_item->oper_reason);
435 <    /* If marked illegal, its already been pulled off of the hub_items list */
436 <    if (!match_item->illegal)
437 <      dlinkDelete(&conf->node, &hub_items);
438 <    MyFree(conf);
439 <    break;
440 <
441 <  case LEAF_TYPE:
442 <    match_item = map_to_conf(conf);
443 <    MyFree(match_item->user);
444 <    MyFree(match_item->host);
445 <    MyFree(match_item->reason);
446 <    MyFree(match_item->oper_reason);
447 <    /* If marked illegal, its already been pulled off of the leaf_items list */
448 <    if (!match_item->illegal)
449 <      dlinkDelete(&conf->node, &leaf_items);
450 <    MyFree(conf);
451 <    break;
452 <
453 <  case ULINE_TYPE:
454 <    match_item = map_to_conf(conf);
455 <    MyFree(match_item->user);
456 <    MyFree(match_item->host);
457 <    MyFree(match_item->reason);
458 <    MyFree(match_item->oper_reason);
459 <    dlinkDelete(&conf->node, &uconf_items);
460 <    MyFree(conf);
461 <    break;
462 <
463 <  case XLINE_TYPE:
464 <    match_item = map_to_conf(conf);
465 <    MyFree(match_item->user);
466 <    MyFree(match_item->host);
467 <    MyFree(match_item->reason);
468 <    MyFree(match_item->oper_reason);
469 <    dlinkDelete(&conf->node, &xconf_items);
470 <    MyFree(conf);
471 <    break;
472 < #ifdef HAVE_LIBPCRE
473 <  case RKLINE_TYPE:
474 <    aconf = map_to_conf(conf);
475 <    MyFree(aconf->regexuser);
476 <    MyFree(aconf->regexhost);
477 <    MyFree(aconf->user);
478 <    MyFree(aconf->host);
479 <    MyFree(aconf->reason);
480 <    MyFree(aconf->oper_reason);
481 <    dlinkDelete(&conf->node, &rkconf_items);
482 <    MyFree(conf);
483 <    break;
484 <
485 <  case RXLINE_TYPE:
486 <    MyFree(conf->regexpname);
487 <    match_item = map_to_conf(conf);
488 <    MyFree(match_item->user);
489 <    MyFree(match_item->host);
490 <    MyFree(match_item->reason);
491 <    MyFree(match_item->oper_reason);
492 <    dlinkDelete(&conf->node, &rxconf_items);
493 <    MyFree(conf);
494 <    break;
193 >  if (conf->rsa_public_key)
194 >    RSA_free(conf->rsa_public_key);
195   #endif
196 <  case NRESV_TYPE:
197 <    match_item = map_to_conf(conf);
198 <    MyFree(match_item->user);
199 <    MyFree(match_item->host);
500 <    MyFree(match_item->reason);
501 <    MyFree(match_item->oper_reason);
502 <    dlinkDelete(&conf->node, &nresv_items);
503 <
504 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
505 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
506 <        free_dlink_node(m);
507 <
508 <    MyFree(conf);
509 <    break;
510 <
511 <  case GDENY_TYPE:
512 <    aconf = map_to_conf(conf);
513 <    MyFree(aconf->user);
514 <    MyFree(aconf->host);
515 <    dlinkDelete(&conf->node, &gdeny_items);
516 <    MyFree(conf);
517 <    break;
518 <
519 <  case CLUSTER_TYPE:
520 <    dlinkDelete(&conf->node, &cluster_items);
521 <    MyFree(conf);
522 <    break;
523 <
524 <  case CRESV_TYPE:
525 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
526 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
527 <        free_dlink_node(m);
528 <
529 <    MyFree(conf);
530 <    break;
531 <
532 <  case CLASS_TYPE:
533 <    dlinkDelete(&conf->node, &class_items);
534 <    MyFree(conf);
535 <    break;
536 <
537 <  case SERVICE_TYPE:
538 <    dlinkDelete(&conf->node, &service_items);
539 <    MyFree(conf);
540 <    break;
541 <
542 <  default:
543 <    break;
196 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->hub_list.head)
197 >  {
198 >    MyFree(ptr->data);
199 >    free_dlink_node(ptr);
200    }
545 }
546
547 /* free_access_item()
548 *
549 * inputs       - pointer to conf to free
550 * output       - none
551 * side effects - crucial password fields are zeroed, conf is freed
552 */
553 void
554 free_access_item(struct AccessItem *aconf)
555 {
556  struct ConfItem *conf;
557
558  if (aconf == NULL)
559    return;
560  conf = unmap_conf_item(aconf);
561  delete_conf_item(conf);
562 }
201  
202 < static const unsigned int shared_bit_table[] =
565 <  { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
566 <
567 < /* report_confitem_types()
568 < *
569 < * inputs       - pointer to client requesting confitem report
570 < *              - ConfType to report
571 < * output       - none
572 < * side effects -
573 < */
574 < void
575 < report_confitem_types(struct Client *source_p, ConfType type, int temp)
576 < {
577 <  dlink_node *ptr = NULL;
578 <  struct ConfItem *conf = NULL;
579 <  struct AccessItem *aconf = NULL;
580 <  struct MatchItem *matchitem = NULL;
581 <  struct ClassItem *classitem = NULL;
582 <  char buf[12];
583 <  char *p = NULL;
584 <  const char *pfx = NULL;
585 <
586 <  switch (type)
202 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->leaf_list.head)
203    {
204 <  case GDENY_TYPE:
205 <    DLINK_FOREACH(ptr, gdeny_items.head)
206 <    {
591 <      conf = ptr->data;
592 <      aconf = map_to_conf(conf);
593 <
594 <      p = buf;
595 <
596 <      if (aconf->flags & GDENY_BLOCK)
597 <        *p++ = 'B';
598 <      else
599 <        *p++ = 'b';
600 <
601 <      if (aconf->flags & GDENY_REJECT)
602 <        *p++ = 'R';
603 <      else
604 <        *p++ = 'r';
605 <
606 <      *p = '\0';
607 <
608 <      sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
609 <                 me.name, RPL_STATSDEBUG, source_p->name,
610 <                 aconf->user, aconf->host, conf->name, buf);
611 <    }
612 <    break;
613 <
614 <  case XLINE_TYPE:
615 <    DLINK_FOREACH(ptr, xconf_items.head)
616 <    {
617 <      conf = ptr->data;
618 <      matchitem = map_to_conf(conf);
619 <
620 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
621 <                 me.name, source_p->name,
622 <                 matchitem->hold ? "x": "X", matchitem->count,
623 <                 conf->name, matchitem->reason);
624 <    }
625 <    break;
626 <
627 < #ifdef HAVE_LIBPCRE
628 <  case RXLINE_TYPE:
629 <    DLINK_FOREACH(ptr, rxconf_items.head)
630 <    {
631 <      conf = ptr->data;
632 <      matchitem = map_to_conf(conf);
633 <
634 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
635 <                 me.name, source_p->name,
636 <                 matchitem->hold ? "xR": "XR", matchitem->count,
637 <                 conf->name, matchitem->reason);
638 <    }
639 <    break;
640 <
641 <  case RKLINE_TYPE:
642 <    pfx = temp ? "kR" : "KR";
643 <
644 <    DLINK_FOREACH(ptr, rkconf_items.head)
645 <    {
646 <      aconf = map_to_conf((conf = ptr->data));
647 <
648 <      if (temp && !(conf->flags & CONF_FLAGS_TEMPORARY))
649 <        continue;
650 <
651 <      sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
652 <                 source_p->name, pfx, aconf->host, aconf->user,
653 <                 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
654 <    }
655 <    break;
656 < #endif
657 <
658 <  case ULINE_TYPE:
659 <    DLINK_FOREACH(ptr, uconf_items.head)
660 <    {
661 <      conf = ptr->data;
662 <      matchitem = map_to_conf(conf);
663 <
664 <      p = buf;
665 <
666 <      /* some of these are redundant for the sake of
667 <       * consistency with cluster{} flags
668 <       */
669 <      *p++ = 'c';
670 <      flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
671 <
672 <      sendto_one(source_p, form_str(RPL_STATSULINE),
673 <                 me.name, source_p->name, conf->name,
674 <                 matchitem->user?matchitem->user: "*",
675 <                 matchitem->host?matchitem->host: "*", buf);
676 <    }
677 <
678 <    DLINK_FOREACH(ptr, cluster_items.head)
679 <    {
680 <      conf = ptr->data;
681 <
682 <      p = buf;
683 <
684 <      *p++ = 'C';
685 <      flags_to_ascii(conf->flags, shared_bit_table, p, 0);
686 <
687 <      sendto_one(source_p, form_str(RPL_STATSULINE),
688 <                 me.name, source_p->name, conf->name,
689 <                 "*", "*", buf);
690 <    }
691 <
692 <    break;
693 <
694 <  case OPER_TYPE:
695 <    DLINK_FOREACH(ptr, oconf_items.head)
696 <    {
697 <      conf = ptr->data;
698 <      aconf = map_to_conf(conf);
699 <
700 <      /* Don't allow non opers to see oper privs */
701 <      if (HasUMode(source_p, UMODE_OPER))
702 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
703 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
704 <                   conf->name, oper_privs_as_string(aconf->port),
705 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
706 <      else
707 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
708 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
709 <                   conf->name, "0",
710 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
711 <    }
712 <    break;
713 <
714 <  case CLASS_TYPE:
715 <    DLINK_FOREACH(ptr, class_items.head)
716 <    {
717 <      conf = ptr->data;
718 <      classitem = map_to_conf(conf);
719 <      sendto_one(source_p, form_str(RPL_STATSYLINE),
720 <                 me.name, source_p->name, 'Y',
721 <                 conf->name, PingFreq(classitem),
722 <                 ConFreq(classitem),
723 <                 MaxTotal(classitem), MaxSendq(classitem),
724 <                 CurrUserCount(classitem),
725 <                 classitem->active ? "active" : "disabled");
726 <    }
727 <    break;
728 <
729 <  case CONF_TYPE:
730 <  case CLIENT_TYPE:
731 <    break;
732 <
733 <  case SERVICE_TYPE:
734 <    DLINK_FOREACH(ptr, service_items.head)
735 <    {
736 <      conf = ptr->data;
737 <      sendto_one(source_p, form_str(RPL_STATSSERVICE),
738 <                 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
739 <    }
740 <    break;
741 <
742 <  case SERVER_TYPE:
743 <    DLINK_FOREACH(ptr, server_items.head)
744 <    {
745 <      p = buf;
746 <
747 <      conf = ptr->data;
748 <      aconf = map_to_conf(conf);
749 <
750 <      buf[0] = '\0';
751 <
752 <      if (IsConfAllowAutoConn(aconf))
753 <        *p++ = 'A';
754 <      if (IsConfSSL(aconf))
755 <        *p++ = 'S';
756 <      if (IsConfTopicBurst(aconf))
757 <        *p++ = 'T';
758 <      if (buf[0] == '\0')
759 <        *p++ = '*';
760 <
761 <      *p = '\0';
762 <
763 <      /*
764 <       * Allow admins to see actual ips unless hide_server_ips is enabled
765 <       */
766 <      if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
767 <        sendto_one(source_p, form_str(RPL_STATSCLINE),
768 <                   me.name, source_p->name, 'C', aconf->host,
769 <                   buf, conf->name, aconf->port,
770 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
771 <        else
772 <          sendto_one(source_p, form_str(RPL_STATSCLINE),
773 <                     me.name, source_p->name, 'C',
774 <                     "*@127.0.0.1", buf, conf->name, aconf->port,
775 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
776 <    }
777 <    break;
778 <
779 <  case HUB_TYPE:
780 <    DLINK_FOREACH(ptr, hub_items.head)
781 <    {
782 <      conf = ptr->data;
783 <      matchitem = map_to_conf(conf);
784 <      sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
785 <                 source_p->name, 'H', matchitem->host, conf->name, 0, "*");
786 <    }
787 <    break;
204 >    MyFree(ptr->data);
205 >    free_dlink_node(ptr);
206 >  }
207  
208 <  case LEAF_TYPE:
209 <    DLINK_FOREACH(ptr, leaf_items.head)
210 <    {
792 <      conf = ptr->data;
793 <      matchitem = map_to_conf(conf);
794 <      sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
795 <                 source_p->name, 'L', matchitem->host, conf->name, 0, "*");
796 <    }
797 <    break;
208 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->exempt_list.head)
209 >  {
210 >    struct exempt *exptr = ptr->data;
211  
212 <  case GLINE_TYPE:
213 <  case KLINE_TYPE:
214 <  case DLINE_TYPE:
215 <  case EXEMPTDLINE_TYPE:
803 <  case CRESV_TYPE:
804 <  case NRESV_TYPE:
805 <  case CLUSTER_TYPE:
806 <  default:
807 <    break;
212 >    MyFree(exptr->name);
213 >    MyFree(exptr->user);
214 >    MyFree(exptr->host);
215 >    MyFree(exptr);
216    }
217 +
218 +  MyFree(conf);
219   }
220  
221   /* check_client()
# Line 821 | Line 231 | report_confitem_types(struct Client *sou
231   *                Look for conf lines which have the same
232   *                status as the flags passed.
233   */
234 < static void *
235 < check_client(va_list args)
234 > int
235 > check_client(struct Client *source_p)
236   {
827  struct Client *source_p = va_arg(args, struct Client *);
828  const char *username = va_arg(args, const char *);
237    int i;
238  
239 <  /* I'm already in big trouble if source_p->localClient is NULL -db */
832 <  if ((i = verify_access(source_p, username)))
239 >  if ((i = verify_access(source_p)))
240      ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
241           source_p->name, source_p->sockhost);
242  
243    switch (i)
244    {
245      case TOO_MANY:
246 <      sendto_realops_flags(UMODE_FULL, L_ALL,
246 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
247                             "Too many on IP for %s (%s).",
248 <                           get_client_name(source_p, SHOW_IP),
249 <                           source_p->sockhost);
248 >                           get_client_name(source_p, SHOW_IP),
249 >                           source_p->sockhost);
250        ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
251 <           get_client_name(source_p, SHOW_IP));
251 >           get_client_name(source_p, SHOW_IP));
252        ++ServerStats.is_ref;
253        exit_client(source_p, &me, "No more connections allowed on that IP");
254        break;
255  
256      case I_LINE_FULL:
257 <      sendto_realops_flags(UMODE_FULL, L_ALL,
258 <                           "I-line is full for %s (%s).",
259 <                           get_client_name(source_p, SHOW_IP),
260 <                           source_p->sockhost);
257 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
258 >                           "auth{} block is full for %s (%s).",
259 >                           get_client_name(source_p, SHOW_IP),
260 >                           source_p->sockhost);
261        ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
262 <           get_client_name(source_p, SHOW_IP));
262 >           get_client_name(source_p, SHOW_IP));
263        ++ServerStats.is_ref;
264        exit_client(source_p, &me,
265 <                "No more connections allowed in your connection class");
265 >                  "No more connections allowed in your connection class");
266        break;
267  
268      case NOT_AUTHORIZED:
269        ++ServerStats.is_ref;
270        /* jdc - lists server name & port connections are on */
271        /*       a purely cosmetical change */
272 <      sendto_realops_flags(UMODE_UNAUTH, L_ALL,
273 <                           "Unauthorized client connection from %s [%s] on [%s/%u].",
274 <                           get_client_name(source_p, SHOW_IP),
275 <                           source_p->sockhost,
276 <                           source_p->localClient->listener->name,
277 <                           source_p->localClient->listener->port);
272 >      sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
273 >                           "Unauthorized client connection from %s [%s] on [%s/%u].",
274 >                           get_client_name(source_p, SHOW_IP),
275 >                           source_p->sockhost,
276 >                           source_p->localClient->listener->name,
277 >                           source_p->localClient->listener->port);
278        ilog(LOG_TYPE_IRCD,
279 <          "Unauthorized client connection from %s on [%s/%u].",
280 <          get_client_name(source_p, SHOW_IP),
281 <          source_p->localClient->listener->name,
282 <          source_p->localClient->listener->port);
283 <
284 <      /* XXX It is prolematical whether it is better to use the
878 <       * capture reject code here or rely on the connecting too fast code.
879 <       * - Dianora
880 <       */
881 <      if (REJECT_HOLD_TIME > 0)
882 <      {
883 <        sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
884 <                   me.name, source_p->name);
885 <        source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
886 <        SetCaptured(source_p);
887 <      }
888 <      else
889 <        exit_client(source_p, &me, "You are not authorized to use this server");
279 >           "Unauthorized client connection from %s on [%s/%u].",
280 >           get_client_name(source_p, SHOW_IP),
281 >           source_p->localClient->listener->name,
282 >           source_p->localClient->listener->port);
283 >
284 >      exit_client(source_p, &me, "You are not authorized to use this server");
285        break;
286  
287     case BANNED_CLIENT:
288 <     /*
894 <      * Don't exit them immediately, play with them a bit.
895 <      * - Dianora
896 <      */
897 <     if (REJECT_HOLD_TIME > 0)
898 <     {
899 <       source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
900 <       SetCaptured(source_p);
901 <     }
902 <     else
903 <       exit_client(source_p, &me, "Banned");
288 >     exit_client(source_p, &me, "Banned");
289       ++ServerStats.is_ref;
290       break;
291  
# Line 909 | Line 294 | check_client(va_list args)
294       break;
295    }
296  
297 <  return (i < 0 ? NULL : source_p);
297 >  return (i < 0 ? 0 : 1);
298   }
299  
300   /* verify_access()
301   *
302   * inputs       - pointer to client to verify
918 *              - pointer to proposed username
303   * output       - 0 if success -'ve if not
304   * side effect  - find the first (best) I line to attach.
305   */
306   static int
307 < verify_access(struct Client *client_p, const char *username)
307 > verify_access(struct Client *client_p)
308   {
309 <  struct AccessItem *aconf = NULL, *rkconf = NULL;
926 <  struct ConfItem *conf = NULL;
309 >  struct MaskItem *conf = NULL;
310    char non_ident[USERLEN + 1] = { '~', '\0' };
928  const char *uhi[3];
311  
312    if (IsGotId(client_p))
313    {
314 <    aconf = find_address_conf(client_p->host, client_p->username,
315 <                             &client_p->localClient->ip,
316 <                             client_p->localClient->aftype,
314 >    conf = find_address_conf(client_p->host, client_p->username,
315 >                             &client_p->localClient->ip,
316 >                             client_p->localClient->aftype,
317                               client_p->localClient->passwd);
318    }
319    else
320    {
321 <    strlcpy(non_ident+1, username, sizeof(non_ident)-1);
322 <    aconf = find_address_conf(client_p->host,non_ident,
323 <                             &client_p->localClient->ip,
324 <                             client_p->localClient->aftype,
325 <                             client_p->localClient->passwd);
321 >    strlcpy(non_ident + 1, client_p->username, sizeof(non_ident) - 1);
322 >    conf = find_address_conf(client_p->host,non_ident,
323 >                             &client_p->localClient->ip,
324 >                             client_p->localClient->aftype,
325 >                             client_p->localClient->passwd);
326    }
327  
328 <  uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
947 <  uhi[1] = client_p->host;
948 <  uhi[2] = client_p->sockhost;
949 <
950 <  rkconf = find_regexp_kline(uhi);
951 <
952 <  if (aconf != NULL)
328 >  if (conf != NULL)
329    {
330 <    if (IsConfClient(aconf) && !rkconf)
330 >    if (IsConfClient(conf))
331      {
332 <      conf = unmap_conf_item(aconf);
957 <
958 <      if (IsConfRedir(aconf))
332 >      if (IsConfRedir(conf))
333        {
334          sendto_one(client_p, form_str(RPL_REDIR),
335                     me.name, client_p->name,
336                     conf->name ? conf->name : "",
337 <                   aconf->port);
338 <        return(NOT_AUTHORIZED);
337 >                   conf->port);
338 >        return NOT_AUTHORIZED;
339        }
340  
341 <      if (IsConfDoIdentd(aconf))
342 <        SetNeedId(client_p);
341 >      if (IsConfDoIdentd(conf))
342 >        SetNeedId(client_p);
343  
344        /* Thanks for spoof idea amm */
345 <      if (IsConfDoSpoofIp(aconf))
345 >      if (IsConfDoSpoofIp(conf))
346        {
347 <        conf = unmap_conf_item(aconf);
348 <
349 <        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
976 <          sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
347 >        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(conf))
348 >          sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
349 >                               "%s spoofing: %s as %s",
350                                 client_p->name, client_p->host, conf->name);
351          strlcpy(client_p->host, conf->name, sizeof(client_p->host));
352 <        SetIPSpoof(client_p);
352 >        AddFlag(client_p, FLAGS_IP_SPOOFING | FLAGS_AUTH_SPOOF);
353        }
354  
355 <      return(attach_iline(client_p, conf));
355 >      return attach_iline(client_p, conf);
356      }
357 <    else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
357 >    else if (IsConfKill(conf) || (ConfigFileEntry.glines && IsConfGline(conf)))
358      {
359 <      /* XXX */
987 <      aconf = rkconf ? rkconf : aconf;
988 <      if (IsConfGline(aconf))
359 >      if (IsConfGline(conf))
360          sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
361                     client_p->name);
362 <      if (ConfigFileEntry.kline_with_reason)
363 <        sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
364 <                  me.name, client_p->name, aconf->reason);
994 <      return(BANNED_CLIENT);
362 >      sendto_one(client_p, ":%s NOTICE %s :*** Banned: %s",
363 >                 me.name, client_p->name, conf->reason);
364 >      return BANNED_CLIENT;
365      }
366    }
367  
368 <  return(NOT_AUTHORIZED);
368 >  return NOT_AUTHORIZED;
369   }
370  
371   /* attach_iline()
# Line 1006 | Line 376 | verify_access(struct Client *client_p, c
376   * side effects - do actual attach
377   */
378   static int
379 < attach_iline(struct Client *client_p, struct ConfItem *conf)
379 > attach_iline(struct Client *client_p, struct MaskItem *conf)
380   {
381 <  struct AccessItem *aconf;
1012 <  struct ClassItem *aclass;
381 >  struct ClassItem *class = NULL;
382    struct ip_entry *ip_found;
383    int a_limit_reached = 0;
384 <  int local = 0, global = 0, ident = 0;
384 >  unsigned int local = 0, global = 0, ident = 0;
385  
386    ip_found = find_or_add_ip(&client_p->localClient->ip);
387    ip_found->count++;
388    SetIpHash(client_p);
389  
390 <  aconf = map_to_conf(conf);
1022 <  if (aconf->class_ptr == NULL)
390 >  if (conf->class == NULL)
391      return NOT_AUTHORIZED;  /* If class is missing, this is best */
392  
393 <  aclass = map_to_conf(aconf->class_ptr);
393 >  class = conf->class;
394  
395    count_user_host(client_p->username, client_p->host,
396                    &global, &local, &ident);
# Line 1031 | Line 399 | attach_iline(struct Client *client_p, st
399     * setting a_limit_reached if any limit is reached.
400     * - Dianora
401     */
402 <  if (MaxTotal(aclass) != 0 && CurrUserCount(aclass) >= MaxTotal(aclass))
402 >  if (class->max_total != 0 && class->ref_count >= class->max_total)
403      a_limit_reached = 1;
404 <  else if (MaxPerIp(aclass) != 0 && ip_found->count > MaxPerIp(aclass))
404 >  else if (class->max_perip != 0 && ip_found->count > class->max_perip)
405      a_limit_reached = 1;
406 <  else if (MaxLocal(aclass) != 0 && local >= MaxLocal(aclass))
406 >  else if (class->max_local != 0 && local >= class->max_local)
407      a_limit_reached = 1;
408 <  else if (MaxGlobal(aclass) != 0 && global >= MaxGlobal(aclass))
408 >  else if (class->max_global != 0 && global >= class->max_global)
409      a_limit_reached = 1;
410 <  else if (MaxIdent(aclass) != 0 && ident >= MaxIdent(aclass) &&
410 >  else if (class->max_ident != 0 && ident >= class->max_ident &&
411             client_p->username[0] != '~')
412      a_limit_reached = 1;
413  
414    if (a_limit_reached)
415    {
416 <    if (!IsConfExemptLimits(aconf))
416 >    if (!IsConfExemptLimits(conf))
417        return TOO_MANY;   /* Already at maximum allowed */
418  
419      sendto_one(client_p,
# Line 1066 | Line 434 | attach_iline(struct Client *client_p, st
434   void
435   init_ip_hash_table(void)
436   {
437 <  ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
1070 <    2 * hard_fdlimit);
437 >  ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
438    memset(ip_hash_table, 0, sizeof(ip_hash_table));
439   }
440  
# Line 1116 | Line 483 | find_or_add_ip(struct irc_ssaddr *ip_in)
483    if (ip_entries_count >= 2 * hard_fdlimit)
484      garbage_collect_ip_entries();
485  
486 <  newptr = BlockHeapAlloc(ip_entry_heap);
486 >  newptr = mp_pool_get(ip_entry_pool);
487 >  memset(newptr, 0, sizeof(*newptr));
488    ip_entries_count++;
489    memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
490  
# Line 1167 | Line 535 | remove_one_ip(struct irc_ssaddr *ip_in)
535      if (ptr->count > 0)
536        ptr->count--;
537      if (ptr->count == 0 &&
538 <        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
538 >        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
539      {
540        if (last_ptr != NULL)
541 <        last_ptr->next = ptr->next;
541 >        last_ptr->next = ptr->next;
542        else
543 <        ip_hash_table[hash_index] = ptr->next;
543 >        ip_hash_table[hash_index] = ptr->next;
544  
545 <      BlockHeapFree(ip_entry_heap, ptr);
545 >      mp_pool_release(ptr);
546        ip_entries_count--;
547        return;
548      }
# Line 1277 | Line 645 | garbage_collect_ip_entries(void)
645            last_ptr->next = ptr->next;
646          else
647            ip_hash_table[i] = ptr->next;
648 <        BlockHeapFree(ip_entry_heap, ptr);
648 >        mp_pool_release(ptr);
649          ip_entries_count--;
650        }
651        else
# Line 1294 | Line 662 | garbage_collect_ip_entries(void)
662   * side effects - Disassociate configuration from the client.
663   *                Also removes a class from the list if marked for deleting.
664   */
665 < int
666 < detach_conf(struct Client *client_p, ConfType type)
665 > void
666 > detach_conf(struct Client *client_p, enum maskitem_type type)
667   {
668 <  dlink_node *ptr, *next_ptr;
1301 <  struct ConfItem *conf;
1302 <  struct ClassItem *aclass;
1303 <  struct AccessItem *aconf;
1304 <  struct ConfItem *aclass_conf;
1305 <  struct MatchItem *match_item;
668 >  dlink_node *ptr = NULL, *next_ptr = NULL;
669  
670    DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
671    {
672 <    conf = ptr->data;
1310 <
1311 <    if (type == CONF_TYPE || conf->type == type)
1312 <    {
1313 <      dlinkDelete(ptr, &client_p->localClient->confs);
1314 <      free_dlink_node(ptr);
672 >    struct MaskItem *conf = ptr->data;
673  
674 <      switch (conf->type)
675 <      {
676 <      case CLIENT_TYPE:
1319 <      case OPER_TYPE:
1320 <      case SERVER_TYPE:
1321 <        aconf = map_to_conf(conf);
1322 <
1323 <        assert(aconf->clients > 0);
674 >    assert(conf->type & (CONF_CLIENT | CONF_OPER | CONF_SERVER));
675 >    assert(conf->ref_count > 0);
676 >    assert(conf->class->ref_count > 0);
677  
678 <        if ((aclass_conf = ClassPtr(aconf)) != NULL)
679 <        {
1327 <          aclass = map_to_conf(aclass_conf);
1328 <
1329 <          assert(aclass->curr_user_count > 0);
1330 <
1331 <          if (conf->type == CLIENT_TYPE)
1332 <            remove_from_cidr_check(&client_p->localClient->ip, aclass);
1333 <          if (--aclass->curr_user_count == 0 && aclass->active == 0)
1334 <            delete_conf_item(aclass_conf);
1335 <        }
1336 <
1337 <        if (--aconf->clients == 0 && IsConfIllegal(aconf))
1338 <          delete_conf_item(conf);
678 >    if (!(conf->type & type))
679 >      continue;
680  
681 <        break;
681 >    dlinkDelete(ptr, &client_p->localClient->confs);
682 >    free_dlink_node(ptr);
683  
684 <      case LEAF_TYPE:
685 <      case HUB_TYPE:
1344 <        match_item = map_to_conf(conf);
1345 <        if (match_item->ref_count == 0 && match_item->illegal)
1346 <          delete_conf_item(conf);
1347 <        break;
1348 <      default:
1349 <        break;
1350 <      }
684 >    if (conf->type == CONF_CLIENT)
685 >      remove_from_cidr_check(&client_p->localClient->ip, conf->class);
686  
687 <      if (type != CONF_TYPE)
688 <        return 0;
687 >    if (--conf->class->ref_count == 0 && conf->class->active == 0)
688 >    {
689 >      class_free(conf->class);
690 >      conf->class = NULL;
691      }
1355  }
692  
693 <  return -1;
693 >    if (--conf->ref_count == 0 && conf->active == 0)
694 >      conf_free(conf);
695 >  }
696   }
697  
698   /* attach_conf()
# Line 1368 | Line 706 | detach_conf(struct Client *client_p, Con
706   *                attachment if there was an old one...
707   */
708   int
709 < attach_conf(struct Client *client_p, struct ConfItem *conf)
709 > attach_conf(struct Client *client_p, struct MaskItem *conf)
710   {
711    if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
712      return 1;
713  
714 <  if (conf->type == CLIENT_TYPE ||
715 <      conf->type == SERVER_TYPE ||
716 <      conf->type == OPER_TYPE)
717 <  {
1380 <    struct AccessItem *aconf = map_to_conf(conf);
1381 <    struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1382 <
1383 <    if (IsConfIllegal(aconf))
1384 <      return NOT_AUTHORIZED;
1385 <
1386 <    if (conf->type == CLIENT_TYPE)
1387 <      if (cidr_limit_reached(IsConfExemptLimits(aconf),
1388 <                             &client_p->localClient->ip, aclass))
1389 <        return TOO_MANY;    /* Already at maximum allowed */
714 >  if (conf->type == CONF_CLIENT)
715 >    if (cidr_limit_reached(IsConfExemptLimits(conf),
716 >                           &client_p->localClient->ip, conf->class))
717 >      return TOO_MANY;    /* Already at maximum allowed */
718  
719 <    CurrUserCount(aclass)++;
720 <    aconf->clients++;
1393 <  }
1394 <  else if (conf->type == HUB_TYPE || conf->type == LEAF_TYPE)
1395 <  {
1396 <    struct MatchItem *match_item = map_to_conf(conf);
1397 <    match_item->ref_count++;
1398 <  }
719 >  conf->class->ref_count++;
720 >  conf->ref_count++;
721  
722    dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
723  
# Line 1415 | Line 737 | attach_connect_block(struct Client *clie
737                       const char *host)
738   {
739    dlink_node *ptr;
740 <  struct ConfItem *conf;
1419 <  struct AccessItem *aconf;
740 >  struct MaskItem *conf = NULL;
741  
742    assert(client_p != NULL);
743    assert(host != NULL);
# Line 1427 | Line 748 | attach_connect_block(struct Client *clie
748    DLINK_FOREACH(ptr, server_items.head)
749    {
750      conf = ptr->data;
1430    aconf = map_to_conf(conf);
751  
752 <    if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
752 >    if (match(conf->name, name) || match(conf->host, host))
753        continue;
754  
755      attach_conf(client_p, conf);
# Line 1439 | Line 759 | attach_connect_block(struct Client *clie
759    return 0;
760   }
761  
1442 /* find_conf_exact()
1443 *
1444 * inputs       - type of ConfItem
1445 *              - pointer to name to find
1446 *              - pointer to username to find
1447 *              - pointer to host to find
1448 * output       - NULL or pointer to conf found
1449 * side effects - find a conf entry which matches the hostname
1450 *                and has the same name.
1451 */
1452 struct ConfItem *
1453 find_conf_exact(ConfType type, const char *name, const char *user,
1454                const char *host)
1455 {
1456  dlink_node *ptr;
1457  dlink_list *list_p;
1458  struct ConfItem *conf = NULL;
1459  struct AccessItem *aconf;
1460
1461  /* Only valid for OPER_TYPE and ...? */
1462  list_p = map_to_list(type);
1463
1464  DLINK_FOREACH(ptr, (*list_p).head)
1465  {
1466    conf = ptr->data;
1467
1468    if (conf->name == NULL)
1469      continue;
1470    aconf = map_to_conf(conf);
1471    if (aconf->host == NULL)
1472      continue;
1473    if (irccmp(conf->name, name) != 0)
1474      continue;
1475
1476    /*
1477    ** Accept if the *real* hostname (usually sockethost)
1478    ** socket host) matches *either* host or name field
1479    ** of the configuration.
1480    */
1481    if (!match(aconf->host, host) || !match(aconf->user, user))
1482      continue;
1483    if (type == OPER_TYPE)
1484    {
1485      struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1486
1487      if (aconf->clients >= MaxTotal(aclass))
1488        continue;
1489    }
1490
1491    return conf;
1492  }
1493
1494  return NULL;
1495 }
1496
762   /* find_conf_name()
763   *
764   * inputs       - pointer to conf link list to search
# Line 1503 | Line 768 | find_conf_exact(ConfType type, const cha
768   * side effects - find a conf entry which matches the name
769   *                and has the given mask.
770   */
771 < struct ConfItem *
772 < find_conf_name(dlink_list *list, const char *name, ConfType type)
771 > struct MaskItem *
772 > find_conf_name(dlink_list *list, const char *name, enum maskitem_type type)
773   {
774    dlink_node *ptr;
775 <  struct ConfItem* conf;
775 >  struct MaskItem* conf;
776  
777    DLINK_FOREACH(ptr, list->head)
778    {
# Line 1516 | Line 781 | find_conf_name(dlink_list *list, const c
781      if (conf->type == type)
782      {
783        if (conf->name && (irccmp(conf->name, name) == 0 ||
784 <                         match(conf->name, name)))
784 >                         !match(conf->name, name)))
785        return conf;
786      }
787    }
# Line 1531 | Line 796 | find_conf_name(dlink_list *list, const c
796   * side effects - none
797   */
798   static dlink_list *
799 < map_to_list(ConfType type)
799 > map_to_list(enum maskitem_type type)
800   {
801    switch(type)
802    {
803 <  case RXLINE_TYPE:
1539 <    return(&rxconf_items);
1540 <    break;
1541 <  case XLINE_TYPE:
803 >  case CONF_XLINE:
804      return(&xconf_items);
805      break;
806 <  case ULINE_TYPE:
806 >  case CONF_ULINE:
807      return(&uconf_items);
808      break;
809 <  case NRESV_TYPE:
809 >  case CONF_NRESV:
810      return(&nresv_items);
811      break;
812 <  case OPER_TYPE:
812 >  case CONF_CRESV:
813 >    return(&cresv_items);
814 >  case CONF_OPER:
815      return(&oconf_items);
816      break;
817 <  case CLASS_TYPE:
1554 <    return(&class_items);
1555 <    break;
1556 <  case SERVER_TYPE:
817 >  case CONF_SERVER:
818      return(&server_items);
819      break;
820 <  case SERVICE_TYPE:
820 >  case CONF_SERVICE:
821      return(&service_items);
822      break;
823 <  case CLUSTER_TYPE:
823 >  case CONF_CLUSTER:
824      return(&cluster_items);
825      break;
1565  case CONF_TYPE:
1566  case GLINE_TYPE:
1567  case KLINE_TYPE:
1568  case DLINE_TYPE:
1569  case CRESV_TYPE:
826    default:
827      return NULL;
828    }
# Line 1578 | Line 834 | map_to_list(ConfType type)
834   *              - pointer to name string to find
835   *              - pointer to user
836   *              - pointer to host
837 < *              - optional action to match on as well
838 < * output       - NULL or pointer to found struct MatchItem
837 > *              - optional flags to match on as well
838 > * output       - NULL or pointer to found struct MaskItem
839   * side effects - looks for a match on name field
840   */
841 < struct ConfItem *
842 < find_matching_name_conf(ConfType type, const char *name, const char *user,
843 <                        const char *host, int action)
841 > struct MaskItem *
842 > find_matching_name_conf(enum maskitem_type type, const char *name, const char *user,
843 >                        const char *host, unsigned int flags)
844   {
845    dlink_node *ptr=NULL;
846 <  struct ConfItem *conf=NULL;
1591 <  struct AccessItem *aconf=NULL;
1592 <  struct MatchItem *match_item=NULL;
846 >  struct MaskItem *conf=NULL;
847    dlink_list *list_p = map_to_list(type);
848  
849    switch (type)
850    {
851 < #ifdef HAVE_LIBPCRE
1598 <  case RXLINE_TYPE:
1599 <      DLINK_FOREACH(ptr, list_p->head)
1600 <      {
1601 <        conf = ptr->data;
1602 <        assert(conf->regexpname);
1603 <
1604 <        if (!ircd_pcre_exec(conf->regexpname, name))
1605 <          return conf;
1606 <      }
1607 <      break;
1608 < #endif
1609 <  case SERVICE_TYPE:
851 >  case CONF_SERVICE:
852      DLINK_FOREACH(ptr, list_p->head)
853      {
854        conf = ptr->data;
# Line 1618 | Line 860 | find_matching_name_conf(ConfType type, c
860      }
861      break;
862  
863 <  case XLINE_TYPE:
864 <  case ULINE_TYPE:
865 <  case NRESV_TYPE:
863 >  case CONF_XLINE:
864 >  case CONF_ULINE:
865 >  case CONF_NRESV:
866 >  case CONF_CRESV:
867      DLINK_FOREACH(ptr, list_p->head)
868      {
869        conf = ptr->data;
870  
1628      match_item = map_to_conf(conf);
871        if (EmptyString(conf->name))
872 <        continue;
873 <      if ((name != NULL) && match_esc(conf->name, name))
872 >        continue;
873 >      if ((name != NULL) && !match(conf->name, name))
874        {
875 <        if ((user == NULL && (host == NULL)))
876 <          return conf;
877 <        if ((match_item->action & action) != action)
875 >        if ((user == NULL && (host == NULL)))
876 >          return conf;
877 >        if ((conf->flags & flags) != flags)
878            continue;
879 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
880 <          return conf;
881 <        if (match(match_item->user, user) && match(match_item->host, host))
882 <          return conf;
879 >        if (EmptyString(conf->user) || EmptyString(conf->host))
880 >          return conf;
881 >        if (!match(conf->user, user) && !match(conf->host, host))
882 >          return conf;
883        }
884      }
885        break;
886  
887 <  case SERVER_TYPE:
887 >  case CONF_SERVER:
888      DLINK_FOREACH(ptr, list_p->head)
889      {
890        conf = ptr->data;
1649      aconf = map_to_conf(conf);
891  
892 <      if ((name != NULL) && match_esc(name, conf->name))
892 >      if ((name != NULL) && !match(name, conf->name))
893          return conf;
894 <      else if ((host != NULL) && match_esc(host, aconf->host))
894 >      else if ((host != NULL) && !match(host, conf->host))
895          return conf;
896      }
897      break;
# Line 1667 | Line 908 | find_matching_name_conf(ConfType type, c
908   *              - pointer to name string to find
909   *              - pointer to user
910   *              - pointer to host
911 < * output       - NULL or pointer to found struct MatchItem
911 > * output       - NULL or pointer to found struct MaskItem
912   * side effects - looks for an exact match on name field
913   */
914 < struct ConfItem *
915 < find_exact_name_conf(ConfType type, const struct Client *who, const char *name,
914 > struct MaskItem *
915 > find_exact_name_conf(enum maskitem_type type, const struct Client *who, const char *name,
916                       const char *user, const char *host)
917   {
918    dlink_node *ptr = NULL;
919 <  struct AccessItem *aconf;
920 <  struct ConfItem *conf;
1680 <  struct MatchItem *match_item;
1681 <  dlink_list *list_p;
1682 <
1683 <  list_p = map_to_list(type);
919 >  struct MaskItem *conf;
920 >  dlink_list *list_p = map_to_list(type);
921  
922    switch(type)
923    {
924 <  case RXLINE_TYPE:
925 <  case XLINE_TYPE:
926 <  case ULINE_TYPE:
927 <  case NRESV_TYPE:
924 >  case CONF_XLINE:
925 >  case CONF_ULINE:
926 >  case CONF_NRESV:
927 >  case CONF_CRESV:
928  
929      DLINK_FOREACH(ptr, list_p->head)
930      {
931        conf = ptr->data;
932 <      match_item = (struct MatchItem *)map_to_conf(conf);
932 >
933        if (EmptyString(conf->name))
934 <        continue;
934 >        continue;
935      
936        if (irccmp(conf->name, name) == 0)
937        {
938 <        if ((user == NULL && (host == NULL)))
939 <          return (conf);
940 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
941 <          return (conf);
942 <        if (match(match_item->user, user) && match(match_item->host, host))
943 <          return (conf);
938 >        if ((user == NULL && (host == NULL)))
939 >          return conf;
940 >        if (EmptyString(conf->user) || EmptyString(conf->host))
941 >          return conf;
942 >        if (!match(conf->user, user) && !match(conf->host, host))
943 >          return conf;
944        }
945      }
946      break;
947  
948 <  case OPER_TYPE:
948 >  case CONF_OPER:
949      DLINK_FOREACH(ptr, list_p->head)
950      {
951        conf = ptr->data;
1715      aconf = map_to_conf(conf);
952  
953        if (EmptyString(conf->name))
954          continue;
# Line 1721 | Line 957 | find_exact_name_conf(ConfType type, cons
957        {
958          if (!who)
959            return conf;
960 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
961 <          return conf;
962 <        if (match(aconf->user, who->username))
960 >        if (EmptyString(conf->user) || EmptyString(conf->host))
961 >          return NULL;
962 >        if (!match(conf->user, who->username))
963          {
964 <          switch (aconf->type)
964 >          switch (conf->htype)
965            {
966              case HM_HOST:
967 <              if (match(aconf->host, who->host) || match(aconf->host, who->sockhost))
968 <                return conf;
967 >              if (!match(conf->host, who->host) || !match(conf->host, who->sockhost))
968 >                if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
969 >                  return conf;
970                break;
971              case HM_IPV4:
972                if (who->localClient->aftype == AF_INET)
973 <                if (match_ipv4(&who->localClient->ip, &aconf->ipnum, aconf->bits))
974 <                  return conf;
973 >                if (match_ipv4(&who->localClient->ip, &conf->addr, conf->bits))
974 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
975 >                    return conf;
976                break;
977   #ifdef IPV6
978              case HM_IPV6:
979                if (who->localClient->aftype == AF_INET6)
980 <                if (match_ipv6(&who->localClient->ip, &aconf->ipnum, aconf->bits))
981 <                  return conf;
980 >                if (match_ipv6(&who->localClient->ip, &conf->addr, conf->bits))
981 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
982 >                    return conf;
983                break;
984   #endif
985              default:
# Line 1752 | Line 991 | find_exact_name_conf(ConfType type, cons
991  
992      break;
993  
994 <  case SERVER_TYPE:
994 >  case CONF_SERVER:
995      DLINK_FOREACH(ptr, list_p->head)
996      {
997        conf = ptr->data;
998 <      aconf = (struct AccessItem *)map_to_conf(conf);
998 >
999        if (EmptyString(conf->name))
1000 <        continue;
1000 >        continue;
1001      
1002        if (name == NULL)
1003        {
1004 <        if (EmptyString(aconf->host))
1005 <          continue;
1006 <        if (irccmp(aconf->host, host) == 0)
1007 <          return(conf);
1004 >        if (EmptyString(conf->host))
1005 >          continue;
1006 >        if (irccmp(conf->host, host) == 0)
1007 >          return conf;
1008        }
1009        else if (irccmp(conf->name, name) == 0)
1010 <      {
1772 <          return (conf);
1773 <      }
1010 >        return conf;
1011      }
1775    break;
1012  
1777  case CLASS_TYPE:
1778    DLINK_FOREACH(ptr, list_p->head)
1779    {
1780      conf = ptr->data;
1781      if (EmptyString(conf->name))
1782        continue;
1783    
1784      if (irccmp(conf->name, name) == 0)
1785        return (conf);
1786    }
1013      break;
1014  
1015    default:
1016      break;
1017    }
1018 <  return(NULL);
1018 >
1019 >  return NULL;
1020   }
1021  
1022   /* rehash()
# Line 1802 | Line 1029 | int
1029   rehash(int sig)
1030   {
1031    if (sig != 0)
1032 <    sendto_realops_flags(UMODE_ALL, L_ALL,
1032 >    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1033                           "Got signal SIGHUP, reloading ircd.conf file");
1034  
1035    restart_resolver();
# Line 1819 | Line 1046 | rehash(int sig)
1046  
1047    load_conf_modules();
1048  
1822  flush_deleted_I_P();
1823
1049    rehashed_klines = 1;
1825 /* XXX */
1826  if (ConfigLoggingEntry.use_logging)
1827    log_close_all();
1050  
1051 <  return(0);
1051 >  return 0;
1052   }
1053  
1054   /* set_default_conf()
# Line 1844 | Line 1066 | set_default_conf(void)
1066    /* verify init_class() ran, this should be an unnecessary check
1067     * but its not much work.
1068     */
1069 <  assert(class_default == (struct ConfItem *) class_items.tail->data);
1069 >  assert(class_default == class_get_list()->tail->data);
1070  
1071   #ifdef HAVE_LIBCRYPTO
1072    ServerInfo.rsa_private_key = NULL;
# Line 1854 | Line 1076 | set_default_conf(void)
1076    /* ServerInfo.name is not rehashable */
1077    /* ServerInfo.name = ServerInfo.name; */
1078    ServerInfo.description = NULL;
1079 <  DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1080 <  DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1079 >  ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1080 >  ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1081  
1082    memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1083    ServerInfo.specific_ipv4_vhost = 0;
# Line 1863 | Line 1085 | set_default_conf(void)
1085    ServerInfo.specific_ipv6_vhost = 0;
1086  
1087    ServerInfo.max_clients = MAXCLIENTS_MAX;
1088 +  ServerInfo.max_nick_length = 9;
1089 +  ServerInfo.max_topic_length = 80;
1090  
1091    ServerInfo.hub = 0;
1092    ServerInfo.dns_host.sin_addr.s_addr = 0;
# Line 1871 | Line 1095 | set_default_conf(void)
1095    AdminInfo.email = NULL;
1096    AdminInfo.description = NULL;
1097  
1098 <  log_close_all();
1098 >  log_del_all();
1099  
1100    ConfigLoggingEntry.use_logging = 1;
1101  
1102    ConfigChannel.disable_fake_channels = 0;
1879  ConfigChannel.restrict_channels = 0;
1880  ConfigChannel.disable_local_channels = 0;
1881  ConfigChannel.use_invex = 1;
1882  ConfigChannel.use_except = 1;
1883  ConfigChannel.use_knock = 1;
1103    ConfigChannel.knock_delay = 300;
1104    ConfigChannel.knock_delay_channel = 60;
1105 <  ConfigChannel.max_chans_per_user = 15;
1106 <  ConfigChannel.quiet_on_ban = 1;
1105 >  ConfigChannel.max_chans_per_user = 25;
1106 >  ConfigChannel.max_chans_per_oper = 50;
1107    ConfigChannel.max_bans = 25;
1108    ConfigChannel.default_split_user_count = 0;
1109    ConfigChannel.default_split_server_count = 0;
1110    ConfigChannel.no_join_on_split = 0;
1111    ConfigChannel.no_create_on_split = 0;
1893  ConfigChannel.burst_topicwho = 1;
1112  
1113    ConfigServerHide.flatten_links = 0;
1114    ConfigServerHide.links_delay = 300;
1115    ConfigServerHide.hidden = 0;
1898  ConfigServerHide.disable_hidden = 0;
1116    ConfigServerHide.hide_servers = 0;
1117 <  DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1117 >  ConfigServerHide.hide_services = 0;
1118 >  ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
1119    ConfigServerHide.hide_server_ips = 0;
1120 +  ConfigServerHide.disable_remote_commands = 0;
1121  
1122    
1123 <  DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1123 >  ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1124    ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1125 +  ConfigFileEntry.cycle_on_host_change = 1;
1126 +  ConfigFileEntry.glines = 0;
1127 +  ConfigFileEntry.gline_time = 12 * 3600;
1128 +  ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
1129    ConfigFileEntry.gline_min_cidr = 16;
1130    ConfigFileEntry.gline_min_cidr6 = 48;
1131    ConfigFileEntry.invisible_on_connect = 1;
1909  ConfigFileEntry.burst_away = 0;
1910  ConfigFileEntry.use_whois_actually = 1;
1132    ConfigFileEntry.tkline_expire_notices = 1;
1133    ConfigFileEntry.hide_spoof_ips = 1;
1134    ConfigFileEntry.ignore_bogus_ts = 0;
1135    ConfigFileEntry.disable_auth = 0;
1915  ConfigFileEntry.disable_remote = 0;
1136    ConfigFileEntry.kill_chase_time_limit = 90;
1137    ConfigFileEntry.default_floodcount = 8;
1138    ConfigFileEntry.failed_oper_notice = 1;
# Line 1926 | Line 1146 | set_default_conf(void)
1146    ConfigFileEntry.anti_spam_exit_message_time = 0;
1147    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1148    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1929  ConfigFileEntry.kline_with_reason = 1;
1930  ConfigFileEntry.kline_reason = NULL;
1149    ConfigFileEntry.warn_no_nline = 1;
1150    ConfigFileEntry.stats_o_oper_only = 0;
1151    ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
1152    ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
1153    ConfigFileEntry.stats_P_oper_only = 0;
1154 +  ConfigFileEntry.stats_u_oper_only = 0;
1155    ConfigFileEntry.caller_id_wait = 60;
1156    ConfigFileEntry.opers_bypass_callerid = 0;
1157    ConfigFileEntry.pace_wait = 10;
# Line 1942 | Line 1161 | set_default_conf(void)
1161    ConfigFileEntry.no_oper_flood = 0;
1162    ConfigFileEntry.true_no_oper_flood = 0;
1163    ConfigFileEntry.oper_pass_resv = 1;
1945  ConfigFileEntry.glines = 0;
1946  ConfigFileEntry.gline_time = 12 * 3600;
1164    ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1948  ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1165    ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1166    ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1167      UMODE_OPERWALL | UMODE_WALLOP;
# Line 1954 | Line 1170 | set_default_conf(void)
1170    ConfigFileEntry.throttle_time = 10;
1171   }
1172  
1173 + static void
1174 + validate_conf(void)
1175 + {
1176 +  if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1177 +    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1178 +
1179 +  if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1180 +    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1181 +
1182 +  if (ServerInfo.network_name == NULL)
1183 +    ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1184 +
1185 +  if (ServerInfo.network_desc == NULL)
1186 +    ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1187 +
1188 +  if (ConfigFileEntry.service_name == NULL)
1189 +    ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1190 +
1191 +  ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1192 + }
1193 +
1194   /* read_conf()
1195   *
1196   * inputs       - file descriptor pointing to config file to use
# Line 1967 | Line 1204 | read_conf(FILE *file)
1204  
1205    set_default_conf(); /* Set default values prior to conf parsing */
1206    conf_parser_ctx.pass = 1;
1207 <  yyparse();          /* pick up the classes first */
1207 >  yyparse();          /* pick up the classes first */
1208  
1209    rewind(file);
1210  
# Line 1975 | Line 1212 | read_conf(FILE *file)
1212    yyparse();          /* Load the values from the conf */
1213    validate_conf();    /* Check to make sure some values are still okay. */
1214                        /* Some global values are also loaded here. */
1215 <  check_class();      /* Make sure classes are valid */
1979 < }
1980 <
1981 < static void
1982 < validate_conf(void)
1983 < {
1984 <  if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1985 <    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1986 <
1987 <  if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1988 <    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1989 <
1990 <  if (ServerInfo.network_name == NULL)
1991 <    DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1992 <
1993 <  if (ServerInfo.network_desc == NULL)
1994 <    DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1995 <
1996 <  if (ConfigFileEntry.service_name == NULL)
1997 <    DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1998 <
1999 <  if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
2000 <      (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
2001 <    ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
2002 <
2003 <  ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1215 >  class_delete_marked();      /* Make sure classes are valid */
1216   }
1217  
1218   /* lookup_confhost()
# Line 2008 | Line 1220 | validate_conf(void)
1220   * start DNS lookups of all hostnames in the conf
1221   * line and convert an IP addresses in a.b.c.d number for to IP#s.
1222   */
1223 < static void
1224 < lookup_confhost(struct ConfItem *conf)
1223 > void
1224 > lookup_confhost(struct MaskItem *conf)
1225   {
2014  struct AccessItem *aconf;
1226    struct addrinfo hints, *res;
1227  
2017  aconf = map_to_conf(conf);
2018
2019  if (EmptyString(aconf->host) ||
2020      EmptyString(aconf->user))
2021  {
2022    ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
2023         aconf->host, conf->name);
2024    return;
2025  }
2026
2027  if (strchr(aconf->host, '*') ||
2028      strchr(aconf->host, '?'))
2029    return;
2030
1228    /* Do name lookup now on hostnames given and store the
1229     * ip numbers in conf structure.
1230     */
# Line 2039 | Line 1236 | lookup_confhost(struct ConfItem *conf)
1236    /* Get us ready for a bind() and don't bother doing dns lookup */
1237    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1238  
1239 <  if (getaddrinfo(aconf->host, NULL, &hints, &res))
1239 >  if (getaddrinfo(conf->host, NULL, &hints, &res))
1240    {
1241 <    conf_dns_lookup(aconf);
1241 >    conf_dns_lookup(conf);
1242      return;
1243    }
1244  
1245    assert(res != NULL);
1246  
1247 <  memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
1248 <  aconf->ipnum.ss_len = res->ai_addrlen;
1249 <  aconf->ipnum.ss.ss_family = res->ai_family;
1247 >  memcpy(&conf->addr, res->ai_addr, res->ai_addrlen);
1248 >  conf->addr.ss_len = res->ai_addrlen;
1249 >  conf->addr.ss.ss_family = res->ai_family;
1250 >
1251    freeaddrinfo(res);
1252   }
1253  
# Line 2064 | Line 1262 | int
1262   conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1263   {
1264    struct ip_entry *ip_found;
1265 <  struct AccessItem *aconf = find_dline_conf(addr, aftype);
1265 >  struct MaskItem *conf = find_dline_conf(addr, aftype);
1266  
1267    /* DLINE exempt also gets you out of static limits/pacing... */
1268 <  if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1268 >  if (conf && (conf->type == CONF_EXEMPT))
1269      return 0;
1270  
1271 <  if (aconf != NULL)
1271 >  if (conf != NULL)
1272      return BANNED_CLIENT;
1273  
1274    ip_found = find_or_add_ip(addr);
# Line 2086 | Line 1284 | conf_connect_allowed(struct irc_ssaddr *
1284    return 0;
1285   }
1286  
2089 static struct AccessItem *
2090 find_regexp_kline(const char *uhi[])
2091 {
2092 #ifdef HAVE_LIBPCRE
2093  const dlink_node *ptr = NULL;
2094
2095  DLINK_FOREACH(ptr, rkconf_items.head)
2096  {
2097    struct AccessItem *aptr = map_to_conf(ptr->data);
2098
2099    assert(aptr->regexuser);
2100    assert(aptr->regexhost);
2101
2102    if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2103        (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2104         !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2105      return aptr;
2106  }
2107 #endif
2108  return NULL;
2109 }
2110
1287   /* find_kill()
1288   *
1289   * inputs       - pointer to client structure
1290 < * output       - pointer to struct AccessItem if found
1290 > * output       - pointer to struct MaskItem if found
1291   * side effects - See if this user is klined already,
1292 < *                and if so, return struct AccessItem pointer
1292 > *                and if so, return struct MaskItem pointer
1293   */
1294 < struct AccessItem *
1294 > struct MaskItem *
1295   find_kill(struct Client *client_p)
1296   {
1297 <  struct AccessItem *aconf = NULL;
2122 <  const char *uhi[3];
2123 <
2124 <  uhi[0] = client_p->username;
2125 <  uhi[1] = client_p->host;
2126 <  uhi[2] = client_p->sockhost;
1297 >  struct MaskItem *conf = NULL;
1298  
1299    assert(client_p != NULL);
1300  
1301 <  aconf = find_kline_conf(client_p->host, client_p->username,
1302 <                          &client_p->localClient->ip,
1303 <                          client_p->localClient->aftype);
1304 <  if (aconf == NULL)
2134 <    aconf = find_regexp_kline(uhi);
2135 <
2136 <  if (aconf && (aconf->status & CONF_KLINE))
2137 <    return aconf;
2138 <
2139 <  return NULL;
1301 >  conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1302 >                              CONF_KLINE, client_p->localClient->aftype,
1303 >                              client_p->username, NULL, 1);
1304 >  return conf;
1305   }
1306  
1307 < struct AccessItem *
1307 > struct MaskItem *
1308   find_gline(struct Client *client_p)
1309   {
1310 <  struct AccessItem *aconf;
1310 >  struct MaskItem *conf;
1311  
1312    assert(client_p != NULL);
1313  
1314 <  aconf = find_gline_conf(client_p->host, client_p->username,
1315 <                          &client_p->localClient->ip,
1316 <                          client_p->localClient->aftype);
1317 <
2153 <  if (aconf && (aconf->status & CONF_GLINE))
2154 <    return aconf;
2155 <
2156 <  return NULL;
2157 < }
2158 <
2159 < /* add_temp_line()
2160 < *
2161 < * inputs        - pointer to struct ConfItem
2162 < * output        - none
2163 < * Side effects  - links in given struct ConfItem into
2164 < *                 temporary *line link list
2165 < */
2166 < void
2167 < add_temp_line(struct ConfItem *conf)
2168 < {
2169 <  struct AccessItem *aconf;
2170 <
2171 <  if (conf->type == DLINE_TYPE)
2172 <  {
2173 <    aconf = map_to_conf(conf);
2174 <    SetConfTemporary(aconf);
2175 <    dlinkAdd(conf, &conf->node, &temporary_dlines);
2176 <    MyFree(aconf->user);
2177 <    aconf->user = NULL;
2178 <    add_conf_by_address(CONF_DLINE, aconf);
2179 <  }
2180 <  else if (conf->type == KLINE_TYPE)
2181 <  {
2182 <    aconf = map_to_conf(conf);
2183 <    SetConfTemporary(aconf);
2184 <    dlinkAdd(conf, &conf->node, &temporary_klines);
2185 <    add_conf_by_address(CONF_KILL, aconf);
2186 <  }
2187 <  else if (conf->type == GLINE_TYPE)
2188 <  {
2189 <    aconf = map_to_conf(conf);
2190 <    SetConfTemporary(aconf);
2191 <    dlinkAdd(conf, &conf->node, &temporary_glines);
2192 <    add_conf_by_address(CONF_GLINE, aconf);
2193 <  }
2194 <  else if (conf->type == XLINE_TYPE)
2195 <  {
2196 <    conf->flags |= CONF_FLAGS_TEMPORARY;
2197 <    dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2198 <  }
2199 <  else if (conf->type == RXLINE_TYPE)
2200 <  {
2201 <    conf->flags |= CONF_FLAGS_TEMPORARY;
2202 <    dlinkAdd(conf, make_dlink_node(), &temporary_rxlines);
2203 <  }
2204 <  else if (conf->type == RKLINE_TYPE)
2205 <  {
2206 <    conf->flags |= CONF_FLAGS_TEMPORARY;
2207 <    dlinkAdd(conf, make_dlink_node(), &temporary_rklines);
2208 <  }
2209 <  else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2210 <  {
2211 <    conf->flags |= CONF_FLAGS_TEMPORARY;
2212 <    dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2213 <  }
1314 >  conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1315 >                              CONF_GLINE, client_p->localClient->aftype,
1316 >                              client_p->username, NULL, 1);
1317 >  return conf;
1318   }
1319  
1320   /* cleanup_tklines()
# Line 2223 | Line 1327 | add_temp_line(struct ConfItem *conf)
1327   void
1328   cleanup_tklines(void *notused)
1329   {
1330 <  expire_tklines(&temporary_glines);
1331 <  expire_tklines(&temporary_klines);
1332 <  expire_tklines(&temporary_dlines);
1333 <  expire_tklines(&temporary_xlines);
2230 <  expire_tklines(&temporary_rxlines);
2231 <  expire_tklines(&temporary_rklines);
2232 <  expire_tklines(&temporary_resv);
1330 >  hostmask_expire_temporary();
1331 >  expire_tklines(&xconf_items);
1332 >  expire_tklines(&nresv_items);
1333 >  expire_tklines(&cresv_items);
1334   }
1335  
1336   /* expire_tklines()
# Line 2243 | Line 1344 | expire_tklines(dlink_list *tklist)
1344   {
1345    dlink_node *ptr;
1346    dlink_node *next_ptr;
1347 <  struct ConfItem *conf;
2247 <  struct MatchItem *xconf;
2248 <  struct MatchItem *nconf;
2249 <  struct AccessItem *aconf;
2250 <  struct ResvChannel *cconf;
1347 >  struct MaskItem *conf;
1348  
1349    DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
1350    {
1351      conf = ptr->data;
2255    if (conf->type == GLINE_TYPE ||
2256        conf->type == KLINE_TYPE ||
2257        conf->type == DLINE_TYPE)
2258    {
2259      aconf = (struct AccessItem *)map_to_conf(conf);
2260      if (aconf->hold <= CurrentTime)
2261      {
2262        /* XXX - Do we want GLINE expiry notices?? */
2263        /* Alert opers that a TKline expired - Hwy */
2264        if (ConfigFileEntry.tkline_expire_notices)
2265        {
2266          if (aconf->status & CONF_KILL)
2267          {
2268            sendto_realops_flags(UMODE_ALL, L_ALL,
2269                                 "Temporary K-line for [%s@%s] expired",
2270                                 (aconf->user) ? aconf->user : "*",
2271                                 (aconf->host) ? aconf->host : "*");
2272          }
2273          else if (conf->type == DLINE_TYPE)
2274          {
2275            sendto_realops_flags(UMODE_ALL, L_ALL,
2276                                 "Temporary D-line for [%s] expired",
2277                                 (aconf->host) ? aconf->host : "*");
2278          }
2279        }
1352  
1353 <        dlinkDelete(ptr, tklist);
1354 <        delete_one_address_conf(aconf->host, aconf);
1355 <      }
1356 <    }
2285 <    else if (conf->type == XLINE_TYPE ||
2286 <             conf->type == RXLINE_TYPE)
2287 <    {
2288 <      xconf = (struct MatchItem *)map_to_conf(conf);
2289 <      if (xconf->hold <= CurrentTime)
2290 <      {
2291 <        if (ConfigFileEntry.tkline_expire_notices)
2292 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2293 <                               "Temporary X-line for [%s] %sexpired", conf->name,
2294 <                               conf->type == RXLINE_TYPE ? "(REGEX) " : "");
2295 <        dlinkDelete(ptr, tklist);
2296 <        free_dlink_node(ptr);
2297 <        delete_conf_item(conf);
2298 <      }
2299 <    }
2300 <    else if (conf->type == RKLINE_TYPE)
1353 >    if (!conf->until || conf->until > CurrentTime)
1354 >      continue;
1355 >
1356 >    if (conf->type == CONF_XLINE)
1357      {
1358 <      aconf = map_to_conf(conf);
1359 <      if (aconf->hold <= CurrentTime)
1360 <      {
1361 <        if (ConfigFileEntry.tkline_expire_notices)
2306 <           sendto_realops_flags(UMODE_ALL, L_ALL,
2307 <                                "Temporary K-line for [%s@%s] (REGEX) expired",
2308 <                                (aconf->user) ? aconf->user : "*",
2309 <                                (aconf->host) ? aconf->host : "*");
2310 <        dlinkDelete(ptr, tklist);
2311 <        free_dlink_node(ptr);
2312 <        delete_conf_item(conf);
2313 <      }
1358 >      if (ConfigFileEntry.tkline_expire_notices)
1359 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1360 >                               "Temporary X-line for [%s] expired", conf->name);
1361 >      conf_free(conf);
1362      }
1363 <    else if (conf->type == NRESV_TYPE)
1363 >    else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1364      {
1365 <      nconf = (struct MatchItem *)map_to_conf(conf);
1366 <      if (nconf->hold <= CurrentTime)
2319 <      {
2320 <        if (ConfigFileEntry.tkline_expire_notices)
2321 <          sendto_realops_flags(UMODE_ALL, L_ALL,
1365 >      if (ConfigFileEntry.tkline_expire_notices)
1366 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1367                                 "Temporary RESV for [%s] expired", conf->name);
1368 <        dlinkDelete(ptr, tklist);
2324 <        free_dlink_node(ptr);
2325 <        delete_conf_item(conf);
2326 <      }
2327 <    }
2328 <    else if (conf->type == CRESV_TYPE)
2329 <    {
2330 <      cconf = (struct ResvChannel *)map_to_conf(conf);
2331 <      if (cconf->hold <= CurrentTime)
2332 <      {
2333 <        if (ConfigFileEntry.tkline_expire_notices)
2334 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2335 <                               "Temporary RESV for [%s] expired", cconf->name);
2336 <        delete_channel_resv(cconf);
2337 <      }
1368 >      conf_free(conf);
1369      }
1370    }
1371   }
# Line 2347 | Line 1378 | expire_tklines(dlink_list *tklist)
1378   */
1379   static const struct oper_privs
1380   {
1381 <  const unsigned int oprivs;
1381 >  const unsigned int flag;
1382    const unsigned char c;
1383   } flag_list[] = {
1384 <  { OPER_FLAG_ADMIN,       'A' },
1385 <  { OPER_FLAG_REMOTEBAN,   'B' },
1386 <  { OPER_FLAG_DIE,         'D' },
1387 <  { OPER_FLAG_GLINE,       'G' },
1388 <  { OPER_FLAG_REHASH,      'H' },
1389 <  { OPER_FLAG_K,           'K' },
1390 <  { OPER_FLAG_OPERWALL,    'L' },
1391 <  { OPER_FLAG_N,           'N' },
1392 <  { OPER_FLAG_GLOBAL_KILL, 'O' },
1393 <  { OPER_FLAG_REMOTE,      'R' },
1394 <  { OPER_FLAG_OPER_SPY,    'S' },
1395 <  { OPER_FLAG_UNKLINE,     'U' },
1396 <  { OPER_FLAG_X,           'X' },
1384 >  { OPER_FLAG_ADMIN,          'A' },
1385 >  { OPER_FLAG_REMOTEBAN,      'B' },
1386 >  { OPER_FLAG_DIE,            'D' },
1387 >  { OPER_FLAG_GLINE,          'G' },
1388 >  { OPER_FLAG_REHASH,         'H' },
1389 >  { OPER_FLAG_K,              'K' },
1390 >  { OPER_FLAG_OPERWALL,       'L' },
1391 >  { OPER_FLAG_KILL,           'N' },
1392 >  { OPER_FLAG_KILL_REMOTE,    'O' },
1393 >  { OPER_FLAG_CONNECT,        'P' },
1394 >  { OPER_FLAG_CONNECT_REMOTE, 'Q' },
1395 >  { OPER_FLAG_SQUIT,          'R' },
1396 >  { OPER_FLAG_SQUIT_REMOTE,   'S' },
1397 >  { OPER_FLAG_UNKLINE,        'U' },
1398 >  { OPER_FLAG_X,              'X' },
1399    { 0, '\0' }
1400   };
1401  
# Line 2371 | Line 1404 | oper_privs_as_string(const unsigned int
1404   {
1405    static char privs_out[16];
1406    char *privs_ptr = privs_out;
1407 <  unsigned int i = 0;
1407 >  const struct oper_privs *opriv = flag_list;
1408  
1409 <  for (; flag_list[i].oprivs; ++i)
1409 >  for (; opriv->flag; ++opriv)
1410    {
1411 <    if (port & flag_list[i].oprivs)
1412 <      *privs_ptr++ = flag_list[i].c;
1411 >    if (port & opriv->flag)
1412 >      *privs_ptr++ = opriv->c;
1413      else
1414 <      *privs_ptr++ = ToLowerTab[flag_list[i].c];
1414 >      *privs_ptr++ = ToLower(opriv->c);
1415    }
1416  
1417    *privs_ptr = '\0';
# Line 2392 | Line 1425 | oper_privs_as_string(const unsigned int
1425   *         "oper" is server name for remote opers
1426   * Side effects: None.
1427   */
1428 < char *
1428 > const char *
1429   get_oper_name(const struct Client *client_p)
1430   {
1431 <  dlink_node *cnode;
2399 <  struct ConfItem *conf;
2400 <  struct AccessItem *aconf;
2401 <
1431 >  dlink_node *cnode = NULL;
1432    /* +5 for !,@,{,} and null */
1433    static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
1434  
1435    if (MyConnect(client_p))
1436    {
1437 <    DLINK_FOREACH(cnode, client_p->localClient->confs.head)
1437 >    if ((cnode = client_p->localClient->confs.head))
1438      {
1439 <      conf = cnode->data;
2410 <      aconf = map_to_conf(conf);
1439 >      struct MaskItem *conf = cnode->data;
1440  
1441 <      if (IsConfOperator(aconf))
1441 >      if (IsConfOperator(conf))
1442        {
1443 <        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1443 >        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1444                   client_p->username, client_p->host, conf->name);
1445 <        return buffer;
1445 >        return buffer;
1446        }
1447      }
1448  
# Line 2424 | Line 1453 | get_oper_name(const struct Client *clien
1453    }
1454  
1455    snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1456 <           client_p->username, client_p->host, client_p->servptr->name);
1456 >           client_p->username, client_p->host, client_p->servptr->name);
1457    return buffer;
1458   }
1459  
# Line 2442 | Line 1471 | read_conf_files(int cold)
1471    char chanlimit[32];
1472  
1473    conf_parser_ctx.boot = cold;
1474 <  filename = get_conf_name(CONF_TYPE);
1474 >  filename = ConfigFileEntry.configfile;
1475  
1476    /* We need to know the initial filename for the yyerror() to report
1477       FIXME: The full path is in conffilenamebuf first time since we
# Line 2462 | Line 1491 | read_conf_files(int cold)
1491      }
1492      else
1493      {
1494 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1495 <                           "Unable to read configuration file '%s': %s",
1496 <                           filename, strerror(errno));
1494 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1495 >                           "Unable to read configuration file '%s': %s",
1496 >                           filename, strerror(errno));
1497        return;
1498      }
1499    }
# Line 2475 | Line 1504 | read_conf_files(int cold)
1504    read_conf(conf_parser_ctx.conf_file);
1505    fclose(conf_parser_ctx.conf_file);
1506  
1507 +  log_reopen_all();
1508 +
1509 +  add_isupport("NICKLEN", NULL, ServerInfo.max_nick_length);
1510    add_isupport("NETWORK", ServerInfo.network_name, -1);
1511 <  snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
1512 <           ConfigChannel.use_except ? "e" : "",
2481 <           ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
1511 >
1512 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1513    add_isupport("MAXLIST", chanmodes, -1);
1514    add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1515 +  add_isupport("CHANTYPES", "#", -1);
1516  
1517 <  if (ConfigChannel.disable_local_channels)
1518 <    add_isupport("CHANTYPES", "#", -1);
2487 <  else
2488 <    add_isupport("CHANTYPES", "#&", -1);
2489 <
2490 <  snprintf(chanlimit, sizeof(chanlimit), "%s:%d",
2491 <           ConfigChannel.disable_local_channels ? "#" : "#&",
2492 <           ConfigChannel.max_chans_per_user);
1517 >  snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1518 >           ConfigChannel.max_chans_per_user);
1519    add_isupport("CHANLIMIT", chanlimit, -1);
1520 <  snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
2495 <           ConfigChannel.use_except ? "e" : "",
2496 <           ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
1520 >  snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,imnprstORS");
1521    add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
1522 <
2499 <  if (ConfigChannel.use_except)
2500 <    add_isupport("EXCEPTS", "e", -1);
2501 <  if (ConfigChannel.use_invex)
2502 <    add_isupport("INVEX", "I", -1);
1522 >  add_isupport("TOPICLEN", NULL, ServerInfo.max_topic_length);
1523    add_isupport("CHANMODES", chanmodes, -1);
1524  
1525    /*
# Line 2507 | Line 1527 | read_conf_files(int cold)
1527     * on strlen(form_str(RPL_ISUPPORT))
1528     */
1529    rebuild_isupport_message_line();
2510
2511 #ifdef HAVE_LIBPCRE
2512  parse_conf_file(RKLINE_TYPE, cold);
2513  parse_conf_file(RXLINE_TYPE, cold);
2514 #endif
2515  parse_conf_file(KLINE_TYPE, cold);
2516  parse_conf_file(DLINE_TYPE, cold);
2517  parse_conf_file(XLINE_TYPE, cold);
2518  parse_conf_file(NRESV_TYPE, cold);
2519  parse_conf_file(CRESV_TYPE, cold);
2520 }
2521
2522 /* parse_conf_file()
2523 *
2524 * inputs       - type of conf file to parse
2525 * output       - none
2526 * side effects - conf file for givenconf type is opened and read then parsed
2527 */
2528 static void
2529 parse_conf_file(int type, int cold)
2530 {
2531  FILE *file = NULL;
2532  const char *filename = get_conf_name(type);
2533
2534  if ((file = fopen(filename, "r")) == NULL)
2535  {
2536    if (cold)
2537      ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2538           filename, strerror(errno));
2539    else
2540      sendto_realops_flags(UMODE_ALL, L_ALL,
2541                    "Unable to read configuration file '%s': %s",
2542                           filename, strerror(errno));
2543  }
2544  else
2545  {
2546    parse_csv_file(file, type);
2547    fclose(file);
2548  }
1530   }
1531  
1532   /* clear_out_old_conf()
# Line 2558 | Line 1539 | static void
1539   clear_out_old_conf(void)
1540   {
1541    dlink_node *ptr = NULL, *next_ptr = NULL;
1542 <  struct ConfItem *conf;
2562 <  struct AccessItem *aconf;
2563 <  struct ClassItem *cltmp;
2564 <  struct MatchItem *match_item;
1542 >  struct MaskItem *conf;
1543    dlink_list *free_items [] = {
1544 <    &server_items,   &oconf_items,    &hub_items, &leaf_items,
1545 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1546 <     &nresv_items, &cluster_items,  &gdeny_items, &service_items, NULL
1544 >    &server_items,   &oconf_items,
1545 >     &uconf_items,   &xconf_items,
1546 >     &nresv_items, &cluster_items,  &service_items, &cresv_items, NULL
1547    };
1548  
1549    dlink_list ** iterator = free_items; /* C is dumb */
# Line 2579 | Line 1557 | clear_out_old_conf(void)
1557      DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1558      {
1559        conf = ptr->data;
2582      /* XXX This is less than pretty */
2583      if (conf->type == SERVER_TYPE)
2584      {
2585        aconf = map_to_conf(conf);
1560  
1561 <        if (aconf->clients != 0)
2588 <        {
2589 <          SetConfIllegal(aconf);
2590 <          dlinkDelete(&conf->node, &server_items);
2591 <        }
2592 <        else
2593 <        {
2594 <          delete_conf_item(conf);
2595 <        }
2596 <      }
2597 <      else if (conf->type == OPER_TYPE)
2598 <      {
2599 <        aconf = map_to_conf(conf);
1561 >      dlinkDelete(&conf->node, map_to_list(conf->type));
1562  
1563 <        if (aconf->clients != 0)
1564 <        {
2603 <          SetConfIllegal(aconf);
2604 <          dlinkDelete(&conf->node, &oconf_items);
2605 <        }
2606 <        else
2607 <        {
2608 <          delete_conf_item(conf);
2609 <        }
2610 <      }
2611 <      else if (conf->type == CLIENT_TYPE)
1563 >      /* XXX This is less than pretty */
1564 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1565        {
1566 <        aconf = map_to_conf(conf);
1567 <
2615 <        if (aconf->clients != 0)
2616 <        {
2617 <          SetConfIllegal(aconf);
2618 <        }
2619 <        else
2620 <        {
2621 <          delete_conf_item(conf);
2622 <        }
1566 >        if (!conf->ref_count)
1567 >          conf_free(conf);
1568        }
1569 <      else if (conf->type == XLINE_TYPE  ||
2625 <               conf->type == RXLINE_TYPE ||
2626 <               conf->type == RKLINE_TYPE)
1569 >      else if (conf->type == CONF_XLINE)
1570        {
1571 <        /* temporary (r)xlines are also on
1572 <         * the (r)xconf items list */
2630 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2631 <          continue;
2632 <
2633 <        delete_conf_item(conf);
1571 >        if (!conf->until)
1572 >          conf_free(conf);
1573        }
1574        else
1575 <      {
2637 <        if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2638 <        {
2639 <          match_item = map_to_conf(conf);
2640 <          if (match_item->ref_count <= 0)
2641 <            delete_conf_item(conf);
2642 <          else
2643 <          {
2644 <            match_item->illegal = 1;
2645 <            dlinkDelete(&conf->node, *iterator);
2646 <          }
2647 <        }
2648 <        else
2649 <          delete_conf_item(conf);
2650 <      }
1575 >        conf_free(conf);
1576      }
1577    }
1578  
1579 +  motd_clear();
1580 +
1581    /*
1582     * don't delete the class table, rather mark all entries
1583 <   * for deletion. The table is cleaned up by check_class. - avalon
1583 >   * for deletion. The table is cleaned up by class_delete_marked. - avalon
1584     */
1585 <  DLINK_FOREACH(ptr, class_items.head)
2659 <  {
2660 <    cltmp = map_to_conf(ptr->data);
2661 <
2662 <    if (ptr != class_items.tail)  /* never mark the "default" class */
2663 <      cltmp->active = 0;
2664 <  }
1585 >  class_mark_for_deletion();
1586  
1587    clear_out_address_conf();
1588  
# Line 2697 | Line 1618 | clear_out_old_conf(void)
1618                                                 SSL_OP_NO_TLSv1);
1619   #endif
1620  
2700  /* clean out old resvs from the conf */
2701  clear_conf_resv();
2702
1621    /* clean out AdminInfo */
1622    MyFree(AdminInfo.name);
1623    AdminInfo.name = NULL;
# Line 2708 | Line 1626 | clear_out_old_conf(void)
1626    MyFree(AdminInfo.description);
1627    AdminInfo.description = NULL;
1628  
2711  /* operator{} and class{} blocks are freed above */
1629    /* clean out listeners */
1630    close_listeners();
1631  
2715  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2716   * exempt{} and gecos{} blocks are freed above too
2717   */
2718
1632    /* clean out general */
1633    MyFree(ConfigFileEntry.service_name);
1634    ConfigFileEntry.service_name = NULL;
2722
2723  delete_isupport("INVEX");
2724  delete_isupport("EXCEPTS");
2725 }
2726
2727 /* flush_deleted_I_P()
2728 *
2729 * inputs       - none
2730 * output       - none
2731 * side effects - This function removes I/P conf items
2732 */
2733 static void
2734 flush_deleted_I_P(void)
2735 {
2736  dlink_node *ptr;
2737  dlink_node *next_ptr;
2738  struct ConfItem *conf;
2739  struct AccessItem *aconf;
2740  dlink_list * free_items [] = {
2741    &server_items, &oconf_items, NULL
2742  };
2743  dlink_list ** iterator = free_items; /* C is dumb */
2744
2745  /* flush out deleted I and P lines
2746   * although still in use.
2747   */
2748  for (; *iterator != NULL; iterator++)
2749  {
2750    DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2751    {
2752      conf = ptr->data;
2753      aconf = (struct AccessItem *)map_to_conf(conf);
2754
2755      if (IsConfIllegal(aconf))
2756      {
2757        dlinkDelete(ptr, *iterator);
2758
2759        if (aconf->clients == 0)
2760          delete_conf_item(conf);
2761      }
2762    }
2763  }
2764 }
2765
2766 /* get_conf_name()
2767 *
2768 * inputs       - type of conf file to return name of file for
2769 * output       - pointer to filename for type of conf
2770 * side effects - none
2771 */
2772 const char *
2773 get_conf_name(ConfType type)
2774 {
2775  switch (type)
2776  {
2777    case CONF_TYPE:
2778      return ConfigFileEntry.configfile;
2779      break;
2780    case KLINE_TYPE:
2781      return ConfigFileEntry.klinefile;
2782      break;
2783    case RKLINE_TYPE:
2784      return ConfigFileEntry.rklinefile;
2785      break;
2786    case DLINE_TYPE:
2787      return ConfigFileEntry.dlinefile;
2788      break;
2789    case XLINE_TYPE:
2790      return ConfigFileEntry.xlinefile;
2791      break;
2792    case RXLINE_TYPE:
2793      return ConfigFileEntry.rxlinefile;
2794      break;
2795    case CRESV_TYPE:
2796      return ConfigFileEntry.cresvfile;
2797      break;
2798    case NRESV_TYPE:
2799      return ConfigFileEntry.nresvfile;
2800      break;
2801    case GLINE_TYPE:
2802      return ConfigFileEntry.glinefile;
2803      break;
2804
2805    default:
2806      return NULL;  /* This should NEVER HAPPEN since we call this function
2807                       only with the above values, this will cause us to core
2808                       at some point if this happens so we know where it was */
2809  }
2810 }
2811
2812 #define BAD_PING (-1)
2813
2814 /* get_conf_ping()
2815 *
2816 * inputs       - pointer to struct AccessItem
2817 *              - pointer to a variable that receives ping warning time
2818 * output       - ping frequency
2819 * side effects - NONE
2820 */
2821 static int
2822 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2823 {
2824  struct ClassItem *aclass;
2825  struct AccessItem *aconf;
2826
2827  if (conf != NULL)
2828  {
2829    aconf = (struct AccessItem *)map_to_conf(conf);
2830    if (aconf->class_ptr != NULL)
2831    {
2832      aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2833      *pingwarn = PingWarning(aclass);
2834      return PingFreq(aclass);
2835    }
2836  }
2837
2838  return BAD_PING;
2839 }
2840
2841 /* get_client_class()
2842 *
2843 * inputs       - pointer to client struct
2844 * output       - pointer to name of class
2845 * side effects - NONE
2846 */
2847 const char *
2848 get_client_class(struct Client *target_p)
2849 {
2850  dlink_node *ptr;
2851  struct ConfItem *conf;
2852  struct AccessItem *aconf;
2853
2854  if (target_p != NULL && !IsMe(target_p) &&
2855      target_p->localClient->confs.head != NULL)
2856  {
2857    DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2858    {
2859      conf = ptr->data;
2860
2861      if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2862          conf->type == OPER_TYPE)
2863      {
2864        aconf = (struct AccessItem *) map_to_conf(conf);
2865        if (aconf->class_ptr != NULL)
2866          return aconf->class_ptr->name;
2867      }
2868    }
2869  }
2870
2871  return "default";
2872 }
2873
2874 /* get_client_ping()
2875 *
2876 * inputs       - pointer to client struct
2877 *              - pointer to a variable that receives ping warning time
2878 * output       - ping frequency
2879 * side effects - NONE
2880 */
2881 int
2882 get_client_ping(struct Client *target_p, int *pingwarn)
2883 {
2884  int ping;
2885  struct ConfItem *conf;
2886  dlink_node *nlink;
2887
2888  if (target_p->localClient->confs.head != NULL)
2889    DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2890    {
2891      conf = nlink->data;
2892
2893      if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2894          (conf->type == OPER_TYPE))
2895      {
2896        ping = get_conf_ping(conf, pingwarn);
2897        if (ping > 0)
2898          return ping;
2899      }
2900    }
2901
2902  *pingwarn = 0;
2903  return DEFAULT_PINGFREQUENCY;
2904 }
2905
2906 /* find_class()
2907 *
2908 * inputs       - string name of class
2909 * output       - corresponding Class pointer
2910 * side effects - NONE
2911 */
2912 struct ConfItem *
2913 find_class(const char *classname)
2914 {
2915  struct ConfItem *conf;
2916
2917  if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2918    return conf;
2919
2920  return class_default;
2921 }
2922
2923 /* check_class()
2924 *
2925 * inputs       - NONE
2926 * output       - NONE
2927 * side effects -
2928 */
2929 void
2930 check_class(void)
2931 {
2932  dlink_node *ptr = NULL, *next_ptr = NULL;
2933
2934  DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2935  {
2936    struct ClassItem *aclass = map_to_conf(ptr->data);
2937
2938    if (!aclass->active && !CurrUserCount(aclass))
2939    {
2940      destroy_cidr_class(aclass);
2941      delete_conf_item(ptr->data);
2942    }
2943  }
2944 }
2945
2946 /* init_class()
2947 *
2948 * inputs       - NONE
2949 * output       - NONE
2950 * side effects -
2951 */
2952 void
2953 init_class(void)
2954 {
2955  struct ClassItem *aclass;
2956
2957  class_default = make_conf_item(CLASS_TYPE);
2958
2959  aclass = map_to_conf(class_default);
2960  aclass->active = 1;
2961  DupString(class_default->name, "default");
2962  ConFreq(aclass)  = DEFAULT_CONNECTFREQUENCY;
2963  PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
2964  MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
2965  MaxSendq(aclass) = DEFAULT_SENDQ;
2966
2967  client_check_cb = register_callback("check_client", check_client);
2968 }
2969
2970 /* get_sendq()
2971 *
2972 * inputs       - pointer to client
2973 * output       - sendq for this client as found from its class
2974 * side effects - NONE
2975 */
2976 unsigned int
2977 get_sendq(struct Client *client_p)
2978 {
2979  unsigned int sendq = DEFAULT_SENDQ;
2980  dlink_node *ptr;
2981  struct ConfItem *conf;
2982  struct ConfItem *class_conf;
2983  struct ClassItem *aclass;
2984  struct AccessItem *aconf;
2985
2986  if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2987  {
2988    DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2989    {
2990      conf = ptr->data;
2991      if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2992          || (conf->type == CLIENT_TYPE))
2993      {
2994        aconf = (struct AccessItem *)map_to_conf(conf);
2995        if ((class_conf = aconf->class_ptr) == NULL)
2996          continue;
2997        aclass = (struct ClassItem *)map_to_conf(class_conf);
2998        sendq = MaxSendq(aclass);
2999        return sendq;
3000      }
3001    }
3002  }
3003  /* XXX return a default?
3004   * if here, then there wasn't an attached conf with a sendq
3005   * that is very bad -Dianora
3006   */
3007  return DEFAULT_SENDQ;
1635   }
1636  
1637   /* conf_add_class_to_conf()
# Line 3014 | Line 1641 | get_sendq(struct Client *client_p)
1641   * side effects - Add a class pointer to a conf
1642   */
1643   void
1644 < conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
1644 > conf_add_class_to_conf(struct MaskItem *conf, const char *class_name)
1645   {
3019  struct AccessItem *aconf = map_to_conf(conf);
3020  struct ClassItem *class = NULL;
3021
1646    if (class_name == NULL)
1647    {
1648 <    aconf->class_ptr = class_default;
1648 >    conf->class = class_default;
1649  
1650 <    if (conf->type == CLIENT_TYPE)
1651 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1652 <                           "Warning *** Defaulting to default class for %s@%s",
1653 <                           aconf->user, aconf->host);
1650 >    if (conf->type == CONF_CLIENT)
1651 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1652 >                           "Warning *** Defaulting to default class for %s@%s",
1653 >                           conf->user, conf->host);
1654      else
1655 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1656 <                           "Warning *** Defaulting to default class for %s",
1657 <                           conf->name);
1655 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1656 >                           "Warning *** Defaulting to default class for %s",
1657 >                           conf->name);
1658    }
1659    else
1660 <    aconf->class_ptr = find_class(class_name);
3037 <
3038 <  if (aconf->class_ptr)
3039 <    class = map_to_conf(aconf->class_ptr);
1660 >    conf->class = class_find(class_name, 1);
1661  
1662 <  if (aconf->class_ptr == NULL || !class->active)
1662 >  if (conf->class == NULL)
1663    {
1664 <    if (conf->type == CLIENT_TYPE)
1665 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1666 <                           "Warning *** Defaulting to default class for %s@%s",
1667 <                           aconf->user, aconf->host);
1664 >    if (conf->type == CONF_CLIENT)
1665 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1666 >                           "Warning *** Defaulting to default class for %s@%s",
1667 >                           conf->user, conf->host);
1668      else
1669 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1670 <                           "Warning *** Defaulting to default class for %s",
1671 <                           conf->name);
1672 <    aconf->class_ptr = class_default;
1669 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1670 >                           "Warning *** Defaulting to default class for %s",
1671 >                           conf->name);
1672 >    conf->class = class_default;
1673    }
1674   }
1675  
3055 /* conf_add_server()
3056 *
3057 * inputs       - pointer to config item
3058 *              - pointer to link count already on this conf
3059 * output       - NONE
3060 * side effects - Add a connect block
3061 */
3062 int
3063 conf_add_server(struct ConfItem *conf, const char *class_name)
3064 {
3065  struct AccessItem *aconf;
3066  struct split_nuh_item nuh;
3067  char conf_user[USERLEN + 1];
3068  char conf_host[HOSTLEN + 1];
3069
3070  aconf = map_to_conf(conf);
3071
3072  conf_add_class_to_conf(conf, class_name);
3073
3074  if (!aconf->host || !conf->name)
3075  {
3076    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
3077    ilog(LOG_TYPE_IRCD, "Bad connect block");
3078    return -1;
3079  }
3080
3081  if (EmptyString(aconf->passwd))
3082  {
3083    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
3084                         conf->name);
3085    ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
3086    return -1;
3087  }
3088
3089  nuh.nuhmask  = aconf->host;
3090  nuh.nickptr  = NULL;
3091  nuh.userptr  = conf_user;
3092  nuh.hostptr  = conf_host;
3093
3094  nuh.nicksize = 0;
3095  nuh.usersize = sizeof(conf_user);
3096  nuh.hostsize = sizeof(conf_host);
3097
3098  split_nuh(&nuh);
3099
3100  MyFree(aconf->host);
3101  aconf->host = NULL;
3102
3103  DupString(aconf->user, conf_user); /* somehow username checking for servers
3104                                 got lost in H6/7, will have to be re-added */
3105  DupString(aconf->host, conf_host);
3106
3107  lookup_confhost(conf);
3108
3109  return 0;
3110 }
3111
1676   /* yyerror()
1677   *
1678   * inputs       - message from parser
# Line 3124 | Line 1688 | yyerror(const char *msg)
1688      return;
1689  
1690    strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1691 <  sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
1691 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1692 >                       "\"%s\", line %u: %s: %s",
1693 >                       conffilebuf, lineno + 1, msg, newlinebuf);
1694 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1695 >       conffilebuf, lineno + 1, msg, newlinebuf);
1696 > }
1697 >
1698 > void
1699 > conf_error_report(const char *msg)
1700 > {
1701 >  char newlinebuf[IRCD_BUFSIZE];
1702 >
1703 >  strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1704 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1705 >                       "\"%s\", line %u: %s: %s",
1706                         conffilebuf, lineno + 1, msg, newlinebuf);
1707    ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1708         conffilebuf, lineno + 1, msg, newlinebuf);
# Line 3151 | Line 1729 | valid_tkline(const char *p, int minutes)
1729        return 0;
1730  
1731      result *= 10;
1732 <    result += ((*p) & 0xF);
1732 >    result += (*p & 0xF);
1733    }
1734  
1735    /*
# Line 3177 | Line 1755 | valid_tkline(const char *p, int minutes)
1755    return result;
1756   }
1757  
1758 + /* valid_wild_card_simple()
1759 + *
1760 + * inputs       - data to check for sufficient non-wildcard characters
1761 + * outputs      - 1 if valid, else 0
1762 + * side effects - none
1763 + */
1764 + int
1765 + valid_wild_card_simple(const char *data)
1766 + {
1767 +  const unsigned char *p = (const unsigned char *)data;
1768 +  unsigned char tmpch = '\0';
1769 +  int nonwild = 0;
1770 +
1771 +  while ((tmpch = *p++))
1772 +  {
1773 +    if (tmpch == '\\')
1774 +    {
1775 +      ++p;
1776 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1777 +        return 1;
1778 +    }
1779 +    else if (!IsMWildChar(tmpch))
1780 +    {
1781 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1782 +        return 1;
1783 +    }
1784 +  }
1785 +
1786 +  return 0;
1787 + }
1788 +
1789   /* valid_wild_card()
1790   *
1791   * input        - pointer to client
# Line 3188 | Line 1797 | valid_tkline(const char *p, int minutes)
1797   int
1798   valid_wild_card(struct Client *source_p, int warn, int count, ...)
1799   {
3191  char *p;
1800    char tmpch;
1801    int nonwild = 0;
1802    va_list args;
# Line 3209 | Line 1817 | valid_wild_card(struct Client *source_p,
1817  
1818    while (count--)
1819    {
1820 <    p = va_arg(args, char *);
1820 >    const char *p = va_arg(args, const char *);
1821      if (p == NULL)
1822        continue;
1823  
# Line 3265 | Line 1873 | valid_wild_card(struct Client *source_p,
1873   */
1874   int
1875   parse_aline(const char *cmd, struct Client *source_p,
1876 <            int parc, char **parv,
1877 <            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1878 <            char **target_server, char **reason)
1876 >            int parc, char **parv,
1877 >            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1878 >            char **target_server, char **reason)
1879   {
1880    int found_tkline_time=0;
1881    static char def_reason[] = "No Reason";
# Line 3289 | Line 1897 | parse_aline(const char *cmd, struct Clie
1897      else
1898      {
1899        sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
1900 <                 me.name, source_p->name, cmd);
1900 >                 me.name, source_p->name, cmd);
1901        return -1;
1902      }
1903    }
# Line 3324 | Line 1932 | parse_aline(const char *cmd, struct Clie
1932  
1933        if (target_server == NULL)
1934        {
1935 <        sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
1936 <                   me.name, source_p->name, cmd);
1937 <        return -1;
1935 >        sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
1936 >                   me.name, source_p->name, cmd);
1937 >        return -1;
1938        }
1939  
1940        if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
# Line 3338 | Line 1946 | parse_aline(const char *cmd, struct Clie
1946  
1947        if (parc == 0 || EmptyString(*parv))
1948        {
1949 <        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1950 <                   me.name, source_p->name, cmd);
1951 <        return -1;
1949 >        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1950 >                   me.name, source_p->name, cmd);
1951 >        return -1;
1952        }
1953  
1954        *target_server = *parv;
# Line 3353 | Line 1961 | parse_aline(const char *cmd, struct Clie
1961         * caller probably NULL'd it first, but no harm to do it again -db
1962         */
1963        if (target_server != NULL)
1964 <        *target_server = NULL;
1964 >        *target_server = NULL;
1965      }
1966    }
1967  
# Line 3379 | Line 1987 | parse_aline(const char *cmd, struct Clie
1987      {
1988        *reason = *parv;
1989        if (!valid_comment(source_p, *reason, 1))
1990 <        return -1;
1990 >        return -1;
1991      }
1992      else
1993        *reason = def_reason;
# Line 3418 | Line 2026 | find_user_host(struct Client *source_p,
2026      {
2027        *(hostp++) = '\0';                       /* short and squat */
2028        if (*user_host_or_nick)
2029 <        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
2029 >        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
2030        else
2031 <        strcpy(luser, "*");
2031 >        strcpy(luser, "*");
2032 >
2033        if (*hostp)
2034 <        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
2034 >        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
2035        else
2036 <        strcpy(lhost, "*");
2036 >        strcpy(lhost, "*");
2037      }
2038      else
2039      {
2040        luser[0] = '*';             /* no @ found, assume its *@somehost */
2041 <      luser[1] = '\0';    
2041 >      luser[1] = '\0';
2042        strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
2043      }
2044      
2045      return 1;
2046    }
2047 <  else if (!(flags & NOUSERLOOKUP))
2047 >  else
2048    {
2049      /* Try to find user@host mask from nick */
2050      /* Okay to use source_p as the first param, because source_p == client_p */
# Line 3446 | Line 2055 | find_user_host(struct Client *source_p,
2055      if (IsExemptKline(target_p))
2056      {
2057        if (!IsServer(source_p))
2058 <        sendto_one(source_p,
2059 <                   ":%s NOTICE %s :%s is E-lined",
2060 <                   me.name, source_p->name, target_p->name);
2058 >        sendto_one(source_p,
2059 >                   ":%s NOTICE %s :%s is E-lined",
2060 >                   me.name, source_p->name, target_p->name);
2061        return 0;
2062      }
2063  
# Line 3483 | Line 2092 | find_user_host(struct Client *source_p,
2092   int
2093   valid_comment(struct Client *source_p, char *comment, int warn)
2094   {
3486  if (strchr(comment, '"'))
3487  {
3488    if (warn)
3489      sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3490                 me.name, source_p->name);
3491    return 0;
3492  }
3493
2095    if (strlen(comment) > REASONLEN)
2096      comment[REASONLEN-1] = '\0';
2097  
# Line 3505 | Line 2106 | valid_comment(struct Client *source_p, c
2106   * side effects - none
2107   */
2108   int
2109 < match_conf_password(const char *password, const struct AccessItem *aconf)
2109 > match_conf_password(const char *password, const struct MaskItem *conf)
2110   {
2111    const char *encr = NULL;
2112  
2113 <  if (password == NULL || aconf->passwd == NULL)
2113 >  if (EmptyString(password) || EmptyString(conf->passwd))
2114      return 0;
2115  
2116 <  if (aconf->flags & CONF_FLAGS_ENCRYPTED)
2117 <  {
3517 <    /* use first two chars of the password they send in as salt */
3518 <    /* If the password in the conf is MD5, and ircd is linked
3519 <     * to scrypt on FreeBSD, or the standard crypt library on
3520 <     * glibc Linux, then this code will work fine on generating
3521 <     * the proper encrypted hash for comparison.
3522 <     */
3523 <    if (*aconf->passwd)
3524 <      encr = crypt(password, aconf->passwd);
3525 <    else
3526 <      encr = "";
3527 <  }
2116 >  if (conf->flags & CONF_FLAGS_ENCRYPTED)
2117 >    encr = crypt(password, conf->passwd);
2118    else
2119      encr = password;
2120  
2121 <  return !strcmp(encr, aconf->passwd);
2121 >  return !strcmp(encr, conf->passwd);
2122   }
2123  
2124   /*
# Line 3557 | Line 2147 | cluster_a_line(struct Client *source_p,
2147  
2148    DLINK_FOREACH(ptr, cluster_items.head)
2149    {
2150 <    const struct ConfItem *conf = ptr->data;
2150 >    const struct MaskItem *conf = ptr->data;
2151  
2152      if (conf->flags & cluster_type)
2153        sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
2154 <                         "%s %s %s", command, conf->name, buffer);
2154 >                         "%s %s %s", command, conf->name, buffer);
2155    }
2156   }
2157  
# Line 3651 | Line 2241 | split_nuh(struct split_nuh_item *const i
2241      }
2242    }
2243   }
3654
3655 /*
3656 * flags_to_ascii
3657 *
3658 * inputs       - flags is a bitmask
3659 *              - pointer to table of ascii letters corresponding
3660 *                to each bit
3661 *              - flag 1 for convert ToLower if bit missing
3662 *                0 if ignore.
3663 * output       - none
3664 * side effects - string pointed to by p has bitmap chars written to it
3665 */
3666 static void
3667 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3668               int lowerit)
3669 {
3670  unsigned int mask = 1;
3671  int i = 0;
3672
3673  for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3674  {
3675    if (flags & mask)
3676      *p++ = bit_table[i];
3677    else if (lowerit)
3678      *p++ = ToLower(bit_table[i]);
3679  }
3680  *p = '\0';
3681 }
3682
3683 /*
3684 * cidr_limit_reached
3685 *
3686 * inputs       - int flag allowing over_rule of limits
3687 *              - pointer to the ip to be added
3688 *              - pointer to the class
3689 * output       - non zero if limit reached
3690 *                0 if limit not reached
3691 * side effects -
3692 */
3693 static int
3694 cidr_limit_reached(int over_rule,
3695                   struct irc_ssaddr *ip, struct ClassItem *aclass)
3696 {
3697  dlink_node *ptr = NULL;
3698  struct CidrItem *cidr;
3699
3700  if (NumberPerCidr(aclass) <= 0)
3701    return 0;
3702
3703  if (ip->ss.ss_family == AF_INET)
3704  {
3705    if (CidrBitlenIPV4(aclass) <= 0)
3706      return 0;
3707
3708    DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3709    {
3710      cidr = ptr->data;
3711      if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3712      {
3713        if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3714          return -1;
3715        cidr->number_on_this_cidr++;
3716        return 0;
3717      }
3718    }
3719    cidr = MyMalloc(sizeof(struct CidrItem));
3720    cidr->number_on_this_cidr = 1;
3721    cidr->mask = *ip;
3722    mask_addr(&cidr->mask, CidrBitlenIPV4(aclass));
3723    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3724  }
3725 #ifdef IPV6
3726  else if (CidrBitlenIPV6(aclass) > 0)
3727  {
3728    DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3729    {
3730      cidr = ptr->data;
3731      if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3732      {
3733        if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3734          return -1;
3735        cidr->number_on_this_cidr++;
3736        return 0;
3737      }
3738    }
3739    cidr = MyMalloc(sizeof(struct CidrItem));
3740    cidr->number_on_this_cidr = 1;
3741    cidr->mask = *ip;
3742    mask_addr(&cidr->mask, CidrBitlenIPV6(aclass));
3743    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3744  }
3745 #endif
3746  return 0;
3747 }
3748
3749 /*
3750 * remove_from_cidr_check
3751 *
3752 * inputs       - pointer to the ip to be removed
3753 *              - pointer to the class
3754 * output       - NONE
3755 * side effects -
3756 */
3757 static void
3758 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3759 {
3760  dlink_node *ptr = NULL;
3761  dlink_node *next_ptr = NULL;
3762  struct CidrItem *cidr;
3763
3764  if (NumberPerCidr(aclass) == 0)
3765    return;
3766
3767  if (ip->ss.ss_family == AF_INET)
3768  {
3769    if (CidrBitlenIPV4(aclass) <= 0)
3770      return;
3771
3772    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3773    {
3774      cidr = ptr->data;
3775      if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3776      {
3777        cidr->number_on_this_cidr--;
3778        if (cidr->number_on_this_cidr == 0)
3779        {
3780          dlinkDelete(ptr, &aclass->list_ipv4);
3781          MyFree(cidr);
3782          return;
3783        }
3784      }
3785    }
3786  }
3787 #ifdef IPV6
3788  else if (CidrBitlenIPV6(aclass) > 0)
3789  {
3790    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3791    {
3792      cidr = ptr->data;
3793      if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3794      {
3795        cidr->number_on_this_cidr--;
3796        if (cidr->number_on_this_cidr == 0)
3797        {
3798          dlinkDelete(ptr, &aclass->list_ipv6);
3799          MyFree(cidr);
3800          return;
3801        }
3802      }
3803    }
3804  }
3805 #endif
3806 }
3807
3808 static void
3809 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3810                  dlink_list *old_list, dlink_list *new_list, int changed)
3811 {
3812  dlink_node *ptr;
3813  struct Client *client_p;
3814  struct ConfItem *conf;
3815  struct AccessItem *aconf;
3816
3817  if (!changed)
3818  {
3819    *new_list = *old_list;
3820    old_list->head = old_list->tail = NULL;
3821    old_list->length = 0;
3822    return;
3823  }
3824
3825  DLINK_FOREACH(ptr, local_client_list.head)
3826  {
3827    client_p = ptr->data;
3828    if (client_p->localClient->aftype != aftype)
3829      continue;
3830    if (dlink_list_length(&client_p->localClient->confs) == 0)
3831      continue;
3832
3833    conf = client_p->localClient->confs.tail->data;
3834    if (conf->type == CLIENT_TYPE)
3835    {
3836      aconf = map_to_conf(conf);
3837      if (aconf->class_ptr == oldcl)
3838        cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3839    }
3840  }
3841 }
3842
3843 /*
3844 * rebuild_cidr_class
3845 *
3846 * inputs       - pointer to old conf
3847 *              - pointer to new_class
3848 * output       - none
3849 * side effects - rebuilds the class link list of cidr blocks
3850 */
3851 void
3852 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3853 {
3854  struct ClassItem *old_class = map_to_conf(conf);
3855
3856  if (NumberPerCidr(old_class) > 0 && NumberPerCidr(new_class) > 0)
3857  {
3858    if (CidrBitlenIPV4(old_class) > 0 && CidrBitlenIPV4(new_class) > 0)
3859      rebuild_cidr_list(AF_INET, conf, new_class,
3860                        &old_class->list_ipv4, &new_class->list_ipv4,
3861                        CidrBitlenIPV4(old_class) != CidrBitlenIPV4(new_class));
3862
3863 #ifdef IPV6
3864    if (CidrBitlenIPV6(old_class) > 0 && CidrBitlenIPV6(new_class) > 0)
3865      rebuild_cidr_list(AF_INET6, conf, new_class,
3866                        &old_class->list_ipv6, &new_class->list_ipv6,
3867                        CidrBitlenIPV6(old_class) != CidrBitlenIPV6(new_class));
3868 #endif
3869  }
3870
3871  destroy_cidr_class(old_class);
3872 }
3873
3874 /*
3875 * destroy_cidr_list
3876 *
3877 * inputs       - pointer to class dlink list of cidr blocks
3878 * output       - none
3879 * side effects - completely destroys the class link list of cidr blocks
3880 */
3881 static void
3882 destroy_cidr_list(dlink_list *list)
3883 {
3884  dlink_node *ptr = NULL, *next_ptr = NULL;
3885
3886  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3887  {
3888    dlinkDelete(ptr, list);
3889    MyFree(ptr->data);
3890  }
3891 }
3892
3893 /*
3894 * destroy_cidr_class
3895 *
3896 * inputs       - pointer to class
3897 * output       - none
3898 * side effects - completely destroys the class link list of cidr blocks
3899 */
3900 static void
3901 destroy_cidr_class(struct ClassItem *aclass)
3902 {
3903  destroy_cidr_list(&aclass->list_ipv4);
3904  destroy_cidr_list(&aclass->list_ipv6);
3905 }

Diff Legend

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