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 4321 by michael, Fri Aug 1 16:55:07 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  conf.c: Configuration file functions.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 18 | Line 17
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file conf.c
23 > * \brief Configuration file functions.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28   #include "list.h"
29   #include "ircd_defs.h"
28 #include "balloc.h"
30   #include "conf.h"
31 < #include "s_serv.h"
31 > #include "server.h"
32   #include "resv.h"
33   #include "channel.h"
34   #include "client.h"
35   #include "event.h"
35 #include "hash.h"
36 #include "hook.h"
36   #include "irc_string.h"
38 #include "sprintf_irc.h"
37   #include "s_bsd.h"
38   #include "ircd.h"
39   #include "listener.h"
# Line 45 | Line 43
43   #include "fdlist.h"
44   #include "log.h"
45   #include "send.h"
48 #include "s_gline.h"
46   #include "memory.h"
47 < #include "irc_res.h"
47 > #include "mempool.h"
48 > #include "res.h"
49   #include "userhost.h"
50 < #include "s_user.h"
50 > #include "user.h"
51   #include "channel_mode.h"
52   #include "parse.h"
53 < #include "s_misc.h"
53 > #include "misc.h"
54 > #include "conf_db.h"
55 > #include "conf_class.h"
56 > #include "motd.h"
57  
57 struct Callback *client_check_cb = NULL;
58 struct config_server_hide ConfigServerHide;
58  
59   /* general conf items link list root, other than k lines etc. */
60   dlink_list service_items = { NULL, NULL, 0 };
61   dlink_list server_items  = { NULL, NULL, 0 };
62   dlink_list cluster_items = { NULL, NULL, 0 };
64 dlink_list hub_items     = { NULL, NULL, 0 };
65 dlink_list leaf_items    = { NULL, NULL, 0 };
63   dlink_list oconf_items   = { NULL, NULL, 0 };
64   dlink_list uconf_items   = { NULL, NULL, 0 };
65   dlink_list xconf_items   = { NULL, NULL, 0 };
69 dlink_list rxconf_items  = { NULL, NULL, 0 };
70 dlink_list rkconf_items  = { NULL, NULL, 0 };
66   dlink_list nresv_items   = { NULL, NULL, 0 };
67 < 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 };
67 > dlink_list cresv_items   = { NULL, NULL, 0 };
68  
69   extern unsigned int lineno;
70   extern char linebuf[];
71   extern char conffilebuf[IRCD_BUFSIZE];
86 extern char yytext[];
72   extern int yyparse(); /* defined in y.tab.c */
73  
89 struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
90
74   /* internally defined functions */
92 static void lookup_confhost(struct ConfItem *);
93 static void set_default_conf(void);
94 static void validate_conf(void);
75   static void read_conf(FILE *);
76   static void clear_out_old_conf(void);
97 static void flush_deleted_I_P(void);
77   static void expire_tklines(dlink_list *);
78 < static void garbage_collect_ip_entries(void);
79 < static int hash_ip(struct irc_ssaddr *);
80 < static int verify_access(struct Client *, const char *);
81 < static int attach_iline(struct Client *, struct ConfItem *);
78 > static void ipcache_remove_expired_entries(void *);
79 > static uint32_t hash_ip(const struct irc_ssaddr *);
80 > static int verify_access(struct Client *);
81 > static int attach_iline(struct Client *, struct MaskItem *);
82   static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
83 < static void parse_conf_file(int, int);
105 < static dlink_list *map_to_list(ConfType);
106 < static struct AccessItem *find_regexp_kline(const char *[]);
83 > static dlink_list *map_to_list(enum maskitem_type);
84   static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
85  
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;
86  
87   /* usually, with hash tables, you use a prime number...
88   * but in this case I am dealing with ip addresses,
# Line 126 | Line 92 | static struct ConfItem *class_default;
92  
93   struct ip_entry
94   {
95 +  dlink_node node;                /**< Doubly linked list node. */
96    struct irc_ssaddr ip;
97 <  int count;
98 <  time_t last_attempt;
99 <  struct ip_entry *next;
97 >  unsigned int count;             /**< Number of registered users using this IP */
98 >  unsigned int connection_count;  /**< Number of connections from this IP in the last throttle_time duration */
99 >  time_t last_attempt;            /**< The last time someone connected from this IP */
100   };
101  
102 < static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
103 < static BlockHeap *ip_entry_heap = NULL;
137 < static int ip_entries_count = 0;
138 <
139 <
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;
102 > static dlink_list ip_hash_table[IP_HASH_SIZE];
103 > static mp_pool_t *ip_entry_pool = NULL;
104  
154  conf = (struct ConfItem *)((uintptr_t)aconf -
155                             (uintptr_t)sizeof(struct ConfItem));
156  return(conf);
157 }
105  
106   /* conf_dns_callback()
107   *
108 < * inputs       - pointer to struct AccessItem
108 > * inputs       - pointer to struct MaskItem
109   *              - pointer to DNSReply reply
110   * output       - none
111   * side effects - called when resolver query finishes
# Line 169 | Line 116 | unmap_conf_item(void *aconf)
116   static void
117   conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
118   {
119 <  struct AccessItem *aconf = vptr;
119 >  struct MaskItem *conf = vptr;
120  
121 <  aconf->dns_pending = 0;
121 >  conf->dns_pending = 0;
122  
123 <  if (addr != NULL)
124 <    memcpy(&aconf->ipnum, addr, sizeof(aconf->ipnum));
123 >  if (addr)
124 >    memcpy(&conf->addr, addr, sizeof(conf->addr));
125    else
126 <    aconf->dns_failed = 1;
126 >    conf->dns_failed = 1;
127   }
128  
129   /* conf_dns_lookup()
# Line 186 | Line 133 | conf_dns_callback(void *vptr, const stru
133   * allocate a dns_query and start ns lookup.
134   */
135   static void
136 < conf_dns_lookup(struct AccessItem *aconf)
136 > conf_dns_lookup(struct MaskItem *conf)
137   {
138 <  if (!aconf->dns_pending)
138 >  if (!conf->dns_pending)
139    {
140 <    aconf->dns_pending = 1;
141 <    gethost_byname(conf_dns_callback, aconf, aconf->host);
140 >    conf->dns_pending = 1;
141 >    gethost_byname(conf_dns_callback, conf, conf->host);
142    }
143   }
144  
145 < /* make_conf_item()
146 < *
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)
145 > struct MaskItem *
146 > conf_make(enum maskitem_type type)
147   {
148 <  struct ConfItem *conf = NULL;
149 <  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;
148 >  struct MaskItem *conf = MyCalloc(sizeof(*conf));
149 >  dlink_list *list = NULL;
150  
151 <    case DLINE_TYPE:
152 <      status = CONF_DLINE;
153 <      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;
270 <
271 <  case HUB_TYPE:
272 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
273 <                                       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;
151 >  conf->type   = type;
152 >  conf->active = 1;
153 >  conf->aftype = AF_INET;
154  
155 +  if ((list = map_to_list(type)))
156 +    dlinkAdd(conf, &conf->node, list);
157    return conf;
158   }
159  
160   void
161 < delete_conf_item(struct ConfItem *conf)
161 > conf_free(struct MaskItem *conf)
162   {
163 <  dlink_node *m = NULL;
164 <  struct MatchItem *match_item;
165 <  struct AccessItem *aconf;
166 <  ConfType type = conf->type;
163 >  dlink_node *ptr = NULL, *ptr_next = NULL;
164 >  dlink_list *list = NULL;
165 >
166 >  if (conf->node.next)
167 >    if ((list = map_to_list(conf->type)))
168 >      dlinkDelete(&conf->node, list);
169  
170    MyFree(conf->name);
365  conf->name = NULL;
171  
172 <  switch(type)
173 <  {
174 <  case DLINE_TYPE:
175 <  case EXEMPTDLINE_TYPE:
176 <  case GLINE_TYPE:
177 <  case KLINE_TYPE:
178 <  case CLIENT_TYPE:
179 <  case OPER_TYPE:
180 <  case SERVER_TYPE:
181 <    aconf = map_to_conf(conf);
182 <
183 <    if (aconf->dns_pending)
184 <      delete_resolver_queries(aconf);
185 <    if (aconf->passwd != NULL)
186 <      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);
172 >  if (conf->dns_pending)
173 >    delete_resolver_queries(conf);
174 >  if (conf->passwd)
175 >    memset(conf->passwd, 0, strlen(conf->passwd));
176 >  if (conf->spasswd)
177 >    memset(conf->spasswd, 0, strlen(conf->spasswd));
178 >
179 >  conf->class = NULL;
180 >
181 >  MyFree(conf->passwd);
182 >  MyFree(conf->spasswd);
183 >  MyFree(conf->reason);
184 >  MyFree(conf->certfp);
185 >  MyFree(conf->user);
186 >  MyFree(conf->host);
187   #ifdef HAVE_LIBCRYPTO
188 <    if (aconf->rsa_public_key)
395 <      RSA_free(aconf->rsa_public_key);
396 <    MyFree(aconf->rsa_public_key_file);
397 < #endif
398 <
399 <    /* Yes, sigh. switch on type again */
400 <    switch(type)
401 <    {
402 <    case EXEMPTDLINE_TYPE:
403 <    case DLINE_TYPE:
404 <    case GLINE_TYPE:
405 <    case KLINE_TYPE:
406 <    case CLIENT_TYPE:
407 <      MyFree(conf);
408 <      break;
409 <
410 <    case OPER_TYPE:
411 <      aconf = map_to_conf(conf);
412 <      if (!IsConfIllegal(aconf))
413 <        dlinkDelete(&conf->node, &oconf_items);
414 <      MyFree(conf);
415 <      break;
416 <
417 <    case SERVER_TYPE:
418 <      aconf = map_to_conf(conf);
419 <      if (!IsConfIllegal(aconf))
420 <        dlinkDelete(&conf->node, &server_items);
421 <      MyFree(conf);
422 <      break;
423 <
424 <    default:
425 <      break;
426 <    }
427 <    break;
428 <
429 <  case HUB_TYPE:
430 <    match_item = map_to_conf(conf);
431 <    MyFree(match_item->user);
432 <    MyFree(match_item->host);
433 <    MyFree(match_item->reason);
434 <    MyFree(match_item->oper_reason);
435 <    /* If marked illegal, its already been pulled off of the hub_items list */
436 <    if (!match_item->illegal)
437 <      dlinkDelete(&conf->node, &hub_items);
438 <    MyFree(conf);
439 <    break;
440 <
441 <  case LEAF_TYPE:
442 <    match_item = map_to_conf(conf);
443 <    MyFree(match_item->user);
444 <    MyFree(match_item->host);
445 <    MyFree(match_item->reason);
446 <    MyFree(match_item->oper_reason);
447 <    /* If marked illegal, its already been pulled off of the leaf_items list */
448 <    if (!match_item->illegal)
449 <      dlinkDelete(&conf->node, &leaf_items);
450 <    MyFree(conf);
451 <    break;
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;
188 >  MyFree(conf->cipher_list);
189  
190 <  case RXLINE_TYPE:
191 <    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;
190 >  if (conf->rsa_public_key)
191 >    RSA_free(conf->rsa_public_key);
192   #endif
193 <  case NRESV_TYPE:
194 <    match_item = map_to_conf(conf);
195 <    MyFree(match_item->user);
196 <    MyFree(match_item->host);
197 <    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;
193 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->hub_list.head)
194 >  {
195 >    MyFree(ptr->data);
196 >    dlinkDelete(ptr, &conf->hub_list);
197 >    free_dlink_node(ptr);
198    }
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 }
563
564 static const unsigned int shared_bit_table[] =
565  { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
199  
200 < /* 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)
200 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->leaf_list.head)
201    {
202 <  case GDENY_TYPE:
203 <    DLINK_FOREACH(ptr, gdeny_items.head)
204 <    {
205 <      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;
202 >    MyFree(ptr->data);
203 >    dlinkDelete(ptr, &conf->leaf_list);
204 >    free_dlink_node(ptr);
205 >  }
206  
207 <  case LEAF_TYPE:
208 <    DLINK_FOREACH(ptr, leaf_items.head)
209 <    {
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;
207 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->exempt_list.head)
208 >  {
209 >    struct exempt *exptr = ptr->data;
210  
211 <  case GLINE_TYPE:
212 <  case KLINE_TYPE:
213 <  case DLINE_TYPE:
214 <  case EXEMPTDLINE_TYPE:
215 <  case CRESV_TYPE:
804 <  case NRESV_TYPE:
805 <  case CLUSTER_TYPE:
806 <  default:
807 <    break;
211 >    dlinkDelete(ptr, &conf->exempt_list);
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 */
240 <  if ((i = verify_access(source_p, username)))
833 <    ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
238 >
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");
253 >      exit_client(source_p, "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,
858 <                "No more connections allowed in your connection class");
264 >      exit_client(source_p, "No more connections allowed in your connection class");
265        break;
266  
267      case NOT_AUTHORIZED:
268        ++ServerStats.is_ref;
269        /* jdc - lists server name & port connections are on */
270        /*       a purely cosmetical change */
271 <      sendto_realops_flags(UMODE_UNAUTH, L_ALL,
272 <                           "Unauthorized client connection from %s [%s] on [%s/%u].",
273 <                           get_client_name(source_p, SHOW_IP),
274 <                           source_p->sockhost,
275 <                           source_p->localClient->listener->name,
276 <                           source_p->localClient->listener->port);
271 >      sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
272 >                           "Unauthorized client connection from %s [%s] on [%s/%u].",
273 >                           get_client_name(source_p, SHOW_IP),
274 >                           source_p->sockhost,
275 >                           source_p->localClient->listener->name,
276 >                           source_p->localClient->listener->port);
277        ilog(LOG_TYPE_IRCD,
278 <          "Unauthorized client connection from %s on [%s/%u].",
279 <          get_client_name(source_p, SHOW_IP),
280 <          source_p->localClient->listener->name,
281 <          source_p->localClient->listener->port);
282 <
283 <      /* 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");
278 >           "Unauthorized client connection from %s on [%s/%u].",
279 >           get_client_name(source_p, SHOW_IP),
280 >           source_p->localClient->listener->name,
281 >           source_p->localClient->listener->port);
282 >
283 >      exit_client(source_p, "You are not authorized to use this server");
284        break;
285  
286     case BANNED_CLIENT:
287 <     /*
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");
287 >     exit_client(source_p, "Banned");
288       ++ServerStats.is_ref;
289       break;
290  
# Line 909 | Line 293 | check_client(va_list args)
293       break;
294    }
295  
296 <  return (i < 0 ? NULL : source_p);
296 >  return (i < 0 ? 0 : 1);
297   }
298  
299   /* verify_access()
300   *
301   * inputs       - pointer to client to verify
918 *              - pointer to proposed username
302   * output       - 0 if success -'ve if not
303   * side effect  - find the first (best) I line to attach.
304   */
305   static int
306 < verify_access(struct Client *client_p, const char *username)
306 > verify_access(struct Client *client_p)
307   {
308 <  struct AccessItem *aconf = NULL, *rkconf = NULL;
309 <  struct ConfItem *conf = NULL;
927 <  char non_ident[USERLEN + 1] = { '~', '\0' };
928 <  const char *uhi[3];
308 >  struct MaskItem *conf = NULL;
309 >  char non_ident[USERLEN + 1] = "~";
310  
311    if (IsGotId(client_p))
312    {
313 <    aconf = find_address_conf(client_p->host, client_p->username,
314 <                             &client_p->localClient->ip,
315 <                             client_p->localClient->aftype,
313 >    conf = find_address_conf(client_p->host, client_p->username,
314 >                             &client_p->localClient->ip,
315 >                             client_p->localClient->aftype,
316                               client_p->localClient->passwd);
317    }
318    else
319    {
320 <    strlcpy(non_ident+1, username, sizeof(non_ident)-1);
321 <    aconf = find_address_conf(client_p->host,non_ident,
322 <                             &client_p->localClient->ip,
323 <                             client_p->localClient->aftype,
324 <                             client_p->localClient->passwd);
320 >    strlcpy(non_ident + 1, client_p->username, sizeof(non_ident) - 1);
321 >    conf = find_address_conf(client_p->host,non_ident,
322 >                             &client_p->localClient->ip,
323 >                             client_p->localClient->aftype,
324 >                             client_p->localClient->passwd);
325    }
326  
327 <  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)
327 >  if (conf)
328    {
329 <    if (IsConfClient(aconf) && !rkconf)
329 >    if (IsConfClient(conf))
330      {
331 <      conf = unmap_conf_item(aconf);
957 <
958 <      if (IsConfRedir(aconf))
331 >      if (IsConfRedir(conf))
332        {
333 <        sendto_one(client_p, form_str(RPL_REDIR),
334 <                   me.name, client_p->name,
335 <                   conf->name ? conf->name : "",
336 <                   aconf->port);
964 <        return(NOT_AUTHORIZED);
333 >        sendto_one_numeric(client_p, &me, RPL_REDIR,
334 >                           conf->name ? conf->name : "",
335 >                           conf->port);
336 >        return NOT_AUTHORIZED;
337        }
338  
339 <      if (IsConfDoIdentd(aconf))
340 <        SetNeedId(client_p);
339 >      if (IsConfDoIdentd(conf))
340 >        SetNeedId(client_p);
341  
342        /* Thanks for spoof idea amm */
343 <      if (IsConfDoSpoofIp(aconf))
343 >      if (IsConfDoSpoofIp(conf))
344        {
345 <        conf = unmap_conf_item(aconf);
346 <
347 <        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
976 <          sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
345 >        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(conf))
346 >          sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
347 >                               "%s spoofing: %s as %s",
348                                 client_p->name, client_p->host, conf->name);
349          strlcpy(client_p->host, conf->name, sizeof(client_p->host));
350 <        SetIPSpoof(client_p);
350 >        AddFlag(client_p, FLAGS_IP_SPOOFING | FLAGS_AUTH_SPOOF);
351        }
352  
353 <      return(attach_iline(client_p, conf));
353 >      return attach_iline(client_p, conf);
354      }
355 <    else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
355 >    else if (IsConfKill(conf) || (ConfigFileEntry.glines && IsConfGline(conf)))
356      {
357 <      /* XXX */
358 <      aconf = rkconf ? rkconf : aconf;
359 <      if (IsConfGline(aconf))
360 <        sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
990 <                   client_p->name);
991 <      if (ConfigFileEntry.kline_with_reason)
992 <        sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
993 <                  me.name, client_p->name, aconf->reason);
994 <      return(BANNED_CLIENT);
357 >      if (IsConfGline(conf))
358 >        sendto_one_notice(client_p, &me, ":*** G-lined");
359 >      sendto_one_notice(client_p, &me, ":*** Banned: %s", conf->reason);
360 >      return BANNED_CLIENT;
361      }
362    }
363  
364 <  return(NOT_AUTHORIZED);
364 >  return NOT_AUTHORIZED;
365   }
366  
367   /* attach_iline()
# Line 1006 | Line 372 | verify_access(struct Client *client_p, c
372   * side effects - do actual attach
373   */
374   static int
375 < attach_iline(struct Client *client_p, struct ConfItem *conf)
375 > attach_iline(struct Client *client_p, struct MaskItem *conf)
376   {
377 <  struct AccessItem *aconf;
1012 <  struct ClassItem *aclass;
377 >  struct ClassItem *class = NULL;
378    struct ip_entry *ip_found;
379    int a_limit_reached = 0;
380 <  int local = 0, global = 0, ident = 0;
380 >  unsigned int local = 0, global = 0, ident = 0;
381 >
382 >  assert(conf->class);
383  
384    ip_found = find_or_add_ip(&client_p->localClient->ip);
385    ip_found->count++;
386    SetIpHash(client_p);
387  
388 <  aconf = map_to_conf(conf);
1022 <  if (aconf->class_ptr == NULL)
1023 <    return NOT_AUTHORIZED;  /* If class is missing, this is best */
1024 <
1025 <  aclass = map_to_conf(aconf->class_ptr);
388 >  class = conf->class;
389  
390    count_user_host(client_p->username, client_p->host,
391                    &global, &local, &ident);
# Line 1031 | Line 394 | attach_iline(struct Client *client_p, st
394     * setting a_limit_reached if any limit is reached.
395     * - Dianora
396     */
397 <  if (MaxTotal(aclass) != 0 && CurrUserCount(aclass) >= MaxTotal(aclass))
397 >  if (class->max_total && class->ref_count >= class->max_total)
398      a_limit_reached = 1;
399 <  else if (MaxPerIp(aclass) != 0 && ip_found->count > MaxPerIp(aclass))
399 >  else if (class->max_perip && ip_found->count > class->max_perip)
400      a_limit_reached = 1;
401 <  else if (MaxLocal(aclass) != 0 && local >= MaxLocal(aclass))
401 >  else if (class->max_local && local >= class->max_local)
402      a_limit_reached = 1;
403 <  else if (MaxGlobal(aclass) != 0 && global >= MaxGlobal(aclass))
403 >  else if (class->max_global && global >= class->max_global)
404      a_limit_reached = 1;
405 <  else if (MaxIdent(aclass) != 0 && ident >= MaxIdent(aclass) &&
405 >  else if (class->max_ident && ident >= class->max_ident &&
406             client_p->username[0] != '~')
407      a_limit_reached = 1;
408  
409    if (a_limit_reached)
410    {
411 <    if (!IsConfExemptLimits(aconf))
411 >    if (!IsConfExemptLimits(conf))
412        return TOO_MANY;   /* Already at maximum allowed */
413  
414 <    sendto_one(client_p,
415 <               ":%s NOTICE %s :*** Your connection class is full, "
1053 <               "but you have exceed_limit = yes;", me.name, client_p->name);
414 >    sendto_one_notice(client_p, &me, ":*** Your connection class is full, "
415 >                      "but you have exceed_limit = yes;");
416    }
417  
418    return attach_conf(client_p, conf);
# Line 1064 | Line 426 | attach_iline(struct Client *client_p, st
426   *                      - clear the ip hash table
427   */
428   void
429 < init_ip_hash_table(void)
429 > ipcache_init(void)
430   {
431 <  ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
432 <    2 * hard_fdlimit);
433 <  memset(ip_hash_table, 0, sizeof(ip_hash_table));
431 >  static struct event event_expire_ipcache =
432 >  {
433 >    .name = "ipcache_remove_expired_entries",
434 >    .handler = ipcache_remove_expired_entries,
435 >    .when = 123
436 >  };
437 >
438 >  event_add(&event_expire_ipcache, NULL);
439 >  ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
440   }
441  
442   /* find_or_add_ip()
# Line 1081 | Line 449 | init_ip_hash_table(void)
449   * count set to 0.
450   */
451   static struct ip_entry *
452 < find_or_add_ip(struct irc_ssaddr *ip_in)
452 > find_or_add_ip(struct irc_ssaddr *addr)
453   {
454 <  struct ip_entry *ptr, *newptr;
455 <  int hash_index = hash_ip(ip_in), res;
456 <  struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
454 >  dlink_node *ptr = NULL;
455 >  struct ip_entry *iptr = NULL;
456 >  uint32_t hash_index = hash_ip(addr);
457 >  int res = 0;
458 >  struct sockaddr_in *v4 = (struct sockaddr_in *)addr, *ptr_v4;
459   #ifdef IPV6
460 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
460 >  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr, *ptr_v6;
461   #endif
462  
463 <  for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
463 >  DLINK_FOREACH(ptr, ip_hash_table[hash_index].head)
464    {
465 +    iptr = ptr->data;
466   #ifdef IPV6
467 <    if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
467 >    if (iptr->ip.ss.ss_family != addr->ss.ss_family)
468        continue;
469 <    if (ip_in->ss.ss_family == AF_INET6)
469 >
470 >    if (addr->ss.ss_family == AF_INET6)
471      {
472 <      ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
472 >      ptr_v6 = (struct sockaddr_in6 *)&iptr->ip;
473        res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
474      }
475      else
476   #endif
477      {
478 <      ptr_v4 = (struct sockaddr_in *)&ptr->ip;
478 >      ptr_v4 = (struct sockaddr_in *)&iptr->ip;
479        res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
480      }
481 +
482      if (res == 0)
483 <    {
1111 <      /* Found entry already in hash, return it. */
1112 <      return ptr;
1113 <    }
483 >      return iptr;  /* Found entry already in hash, return it. */
484    }
485  
486 <  if (ip_entries_count >= 2 * hard_fdlimit)
487 <    garbage_collect_ip_entries();
1118 <
1119 <  newptr = BlockHeapAlloc(ip_entry_heap);
1120 <  ip_entries_count++;
1121 <  memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
486 >  iptr = mp_pool_get(ip_entry_pool);
487 >  memcpy(&iptr->ip, addr, sizeof(struct irc_ssaddr));
488  
489 <  newptr->next = ip_hash_table[hash_index];
1124 <  ip_hash_table[hash_index] = newptr;
489 >  dlinkAdd(iptr, &iptr->node, &atable[hash_index]);
490  
491 <  return newptr;
491 >  return iptr;
492   }
493  
494   /* remove_one_ip()
# Line 1136 | Line 501 | find_or_add_ip(struct irc_ssaddr *ip_in)
501   *                 the struct ip_entry is returned to the ip_entry_heap
502   */
503   void
504 < remove_one_ip(struct irc_ssaddr *ip_in)
504 > remove_one_ip(struct irc_ssaddr *addr)
505   {
506 <  struct ip_entry *ptr;
507 <  struct ip_entry *last_ptr = NULL;
508 <  int hash_index = hash_ip(ip_in), res;
509 <  struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
506 >  dlink_node *ptr = NULL;
507 >  uint32_t hash_index = hash_ip(addr);
508 >  int res = 0;
509 >  struct sockaddr_in *v4 = (struct sockaddr_in *)addr, *ptr_v4;
510   #ifdef IPV6
511 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
511 >  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr, *ptr_v6;
512   #endif
513  
514 <  for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
514 >  DLINK_FOREACH(ptr, ip_hash_table[hash_index].head)
515    {
516 +    struct ip_entry *iptr = ptr->data;
517   #ifdef IPV6
518 <    if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
518 >    if (iptr->ip.ss.ss_family != addr->ss.ss_family)
519        continue;
520 <    if (ip_in->ss.ss_family == AF_INET6)
520 >    if (addr->ss.ss_family == AF_INET6)
521      {
522 <      ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
522 >      ptr_v6 = (struct sockaddr_in6 *)&iptr->ip;
523        res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
524      }
525      else
526   #endif
527      {
528 <      ptr_v4 = (struct sockaddr_in *)&ptr->ip;
528 >      ptr_v4 = (struct sockaddr_in *)&iptr->ip;
529        res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
530      }
531 +
532      if (res)
533        continue;
534 <    if (ptr->count > 0)
1168 <      ptr->count--;
1169 <    if (ptr->count == 0 &&
1170 <        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1171 <    {
1172 <      if (last_ptr != NULL)
1173 <        last_ptr->next = ptr->next;
1174 <      else
1175 <        ip_hash_table[hash_index] = ptr->next;
534 >    assert(iptr->count > 0);
535  
536 <      BlockHeapFree(ip_entry_heap, ptr);
537 <      ip_entries_count--;
536 >    if (--iptr->count == 0 &&
537 >        (CurrentTime - iptr->last_attempt) >= ConfigFileEntry.throttle_time)
538 >    {
539 >      dlinkDelete(&iptr->node, &ip_hash_table[hash_index]);
540 >      mp_pool_release(iptr);
541        return;
542      }
1181    last_ptr = ptr;
543    }
544   }
545  
# Line 1188 | Line 549 | remove_one_ip(struct irc_ssaddr *ip_in)
549   * output       - integer value used as index into hash table
550   * side effects - hopefully, none
551   */
552 < static int
553 < hash_ip(struct irc_ssaddr *addr)
552 > static uint32_t
553 > hash_ip(const struct irc_ssaddr *addr)
554   {
555    if (addr->ss.ss_family == AF_INET)
556    {
557 <    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
558 <    int hash;
1198 <    uint32_t ip;
557 >    const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr;
558 >    uint32_t hash = 0, ip = ntohl(v4->sin_addr.s_addr);
559  
560 <    ip   = ntohl(v4->sin_addr.s_addr);
1201 <    hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
560 >    hash = ((ip >> 12) + ip) & (IP_HASH_SIZE - 1);
561      return hash;
562    }
563   #ifdef IPV6
564    else
565    {
566 <    int hash;
567 <    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
1209 <    uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
566 >    const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr;
567 >    uint32_t hash = 0, *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
568  
569      hash  = ip[0] ^ ip[3];
570 <    hash ^= hash >> 16;  
571 <    hash ^= hash >> 8;  
570 >    hash ^= hash >> 16;
571 >    hash ^= hash >> 8;
572      hash  = hash & (IP_HASH_SIZE - 1);
573      return hash;
574    }
# Line 1221 | Line 579 | hash_ip(struct irc_ssaddr *addr)
579  
580   /* count_ip_hash()
581   *
582 < * inputs        - pointer to counter of number of ips hashed
582 > * inputs        - pointer to counter of number of ips hashed
583   *               - pointer to memory used for ip hash
584   * output        - returned via pointers input
585   * side effects  - NONE
# Line 1232 | Line 590 | hash_ip(struct irc_ssaddr *addr)
590   void
591   count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
592   {
1235  struct ip_entry *ptr;
1236  int i;
1237
593    *number_ips_stored = 0;
594    *mem_ips_stored    = 0;
595  
596 <  for (i = 0; i < IP_HASH_SIZE; i++)
596 >  for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
597    {
598 <    for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
599 <    {
1245 <      *number_ips_stored += 1;
1246 <      *mem_ips_stored += sizeof(struct ip_entry);
1247 <    }
598 >    *number_ips_stored += dlink_list_length(&ip_hash_table[i]);
599 >    *mem_ips_stored += dlink_list_length(&ip_hash_table[i]) * sizeof(struct ip_entry);
600    }
601   }
602  
# Line 1255 | Line 607 | count_ip_hash(unsigned int *number_ips_s
607   * side effects - free up all ip entries with no connections
608   */
609   static void
610 < garbage_collect_ip_entries(void)
610 > ipcache_remove_expired_entries(void *unused)
611   {
612 <  struct ip_entry *ptr;
1261 <  struct ip_entry *last_ptr;
1262 <  struct ip_entry *next_ptr;
1263 <  int i;
612 >  dlink_node *ptr = NULL, *ptr_next = NULL;
613  
614 <  for (i = 0; i < IP_HASH_SIZE; i++)
614 >  for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
615    {
616 <    last_ptr = NULL;
1268 <
1269 <    for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
616 >    DLINK_FOREACH_SAFE(ptr, ptr_next, ip_hash_table[i].head)
617      {
618 <      next_ptr = ptr->next;
618 >      struct ip_entry *iptr = ptr->data;
619  
620 <      if (ptr->count == 0 &&
621 <          (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
620 >      if (iptr->count == 0 &&
621 >          (CurrentTime - iptr->last_attempt) >= ConfigFileEntry.throttle_time)
622        {
623 <        if (last_ptr != NULL)
624 <          last_ptr->next = ptr->next;
1278 <        else
1279 <          ip_hash_table[i] = ptr->next;
1280 <        BlockHeapFree(ip_entry_heap, ptr);
1281 <        ip_entries_count--;
623 >        dlinkDelete(&iptr->node, &ip_hash_table[i]);
624 >        mp_pool_release(iptr);
625        }
1283      else
1284        last_ptr = ptr;
626      }
627    }
628   }
# Line 1294 | Line 635 | garbage_collect_ip_entries(void)
635   * side effects - Disassociate configuration from the client.
636   *                Also removes a class from the list if marked for deleting.
637   */
638 < int
639 < detach_conf(struct Client *client_p, ConfType type)
638 > void
639 > detach_conf(struct Client *client_p, enum maskitem_type type)
640   {
641 <  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;
641 >  dlink_node *ptr = NULL, *ptr_next = NULL;
642  
643 <  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
643 >  DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->localClient->confs.head)
644    {
645 <    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);
1315 <
1316 <      switch (conf->type)
1317 <      {
1318 <      case CLIENT_TYPE:
1319 <      case OPER_TYPE:
1320 <      case SERVER_TYPE:
1321 <        aconf = map_to_conf(conf);
1322 <
1323 <        assert(aconf->clients > 0);
1324 <
1325 <        if ((aclass_conf = ClassPtr(aconf)) != NULL)
1326 <        {
1327 <          aclass = map_to_conf(aclass_conf);
645 >    struct MaskItem *conf = ptr->data;
646  
647 <          assert(aclass->curr_user_count > 0);
647 >    assert(conf->type & (CONF_CLIENT | CONF_OPER | CONF_SERVER));
648 >    assert(conf->ref_count > 0);
649 >    assert(conf->class->ref_count > 0);
650  
651 <          if (conf->type == CLIENT_TYPE)
652 <            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);
651 >    if (!(conf->type & type))
652 >      continue;
653  
654 <        break;
654 >    dlinkDelete(ptr, &client_p->localClient->confs);
655 >    free_dlink_node(ptr);
656  
657 <      case LEAF_TYPE:
658 <      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 <      }
657 >    if (conf->type == CONF_CLIENT)
658 >      remove_from_cidr_check(&client_p->localClient->ip, conf->class);
659  
660 <      if (type != CONF_TYPE)
661 <        return 0;
660 >    if (--conf->class->ref_count == 0 && conf->class->active == 0)
661 >    {
662 >      class_free(conf->class);
663 >      conf->class = NULL;
664      }
1355  }
665  
666 <  return -1;
666 >    if (--conf->ref_count == 0 && conf->active == 0)
667 >      conf_free(conf);
668 >  }
669   }
670  
671   /* attach_conf()
# Line 1368 | Line 679 | detach_conf(struct Client *client_p, Con
679   *                attachment if there was an old one...
680   */
681   int
682 < attach_conf(struct Client *client_p, struct ConfItem *conf)
682 > attach_conf(struct Client *client_p, struct MaskItem *conf)
683   {
684 <  if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
684 >  if (dlinkFind(&client_p->localClient->confs, conf))
685      return 1;
686  
687 <  if (conf->type == CLIENT_TYPE ||
688 <      conf->type == SERVER_TYPE ||
689 <      conf->type == OPER_TYPE)
690 <  {
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;
687 >  if (conf->type == CONF_CLIENT)
688 >    if (cidr_limit_reached(IsConfExemptLimits(conf),
689 >                           &client_p->localClient->ip, conf->class))
690 >      return TOO_MANY;    /* Already at maximum allowed */
691  
692 <    if (conf->type == CLIENT_TYPE)
693 <      if (cidr_limit_reached(IsConfExemptLimits(aconf),
1388 <                             &client_p->localClient->ip, aclass))
1389 <        return TOO_MANY;    /* Already at maximum allowed */
1390 <
1391 <    CurrUserCount(aclass)++;
1392 <    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 <  }
692 >  conf->class->ref_count++;
693 >  conf->ref_count++;
694  
695    dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
696  
# Line 1415 | Line 710 | attach_connect_block(struct Client *clie
710                       const char *host)
711   {
712    dlink_node *ptr;
713 <  struct ConfItem *conf;
1419 <  struct AccessItem *aconf;
713 >  struct MaskItem *conf = NULL;
714  
715    assert(client_p != NULL);
716    assert(host != NULL);
# Line 1427 | Line 721 | attach_connect_block(struct Client *clie
721    DLINK_FOREACH(ptr, server_items.head)
722    {
723      conf = ptr->data;
1430    aconf = map_to_conf(conf);
724  
725 <    if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
725 >    if (match(conf->name, name) || match(conf->host, host))
726        continue;
727  
728      attach_conf(client_p, conf);
# Line 1439 | Line 732 | attach_connect_block(struct Client *clie
732    return 0;
733   }
734  
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
735   /* find_conf_name()
736   *
737   * inputs       - pointer to conf link list to search
# Line 1503 | Line 741 | find_conf_exact(ConfType type, const cha
741   * side effects - find a conf entry which matches the name
742   *                and has the given mask.
743   */
744 < struct ConfItem *
745 < find_conf_name(dlink_list *list, const char *name, ConfType type)
744 > struct MaskItem *
745 > find_conf_name(dlink_list *list, const char *name, enum maskitem_type type)
746   {
747    dlink_node *ptr;
748 <  struct ConfItem* conf;
748 >  struct MaskItem* conf;
749  
750    DLINK_FOREACH(ptr, list->head)
751    {
752      conf = ptr->data;
753 <    
753 >
754      if (conf->type == type)
755      {
756 <      if (conf->name && (irccmp(conf->name, name) == 0 ||
757 <                         match(conf->name, name)))
756 >      if (conf->name && (!irccmp(conf->name, name) ||
757 >                         !match(conf->name, name)))
758        return conf;
759      }
760    }
# Line 1531 | Line 769 | find_conf_name(dlink_list *list, const c
769   * side effects - none
770   */
771   static dlink_list *
772 < map_to_list(ConfType type)
772 > map_to_list(enum maskitem_type type)
773   {
774    switch(type)
775    {
776 <  case RXLINE_TYPE:
1539 <    return(&rxconf_items);
1540 <    break;
1541 <  case XLINE_TYPE:
776 >  case CONF_XLINE:
777      return(&xconf_items);
778      break;
779 <  case ULINE_TYPE:
779 >  case CONF_ULINE:
780      return(&uconf_items);
781      break;
782 <  case NRESV_TYPE:
782 >  case CONF_NRESV:
783      return(&nresv_items);
784      break;
785 <  case OPER_TYPE:
785 >  case CONF_CRESV:
786 >    return(&cresv_items);
787 >  case CONF_OPER:
788      return(&oconf_items);
789      break;
790 <  case CLASS_TYPE:
1554 <    return(&class_items);
1555 <    break;
1556 <  case SERVER_TYPE:
790 >  case CONF_SERVER:
791      return(&server_items);
792      break;
793 <  case SERVICE_TYPE:
793 >  case CONF_SERVICE:
794      return(&service_items);
795      break;
796 <  case CLUSTER_TYPE:
796 >  case CONF_CLUSTER:
797      return(&cluster_items);
798      break;
1565  case CONF_TYPE:
1566  case GLINE_TYPE:
1567  case KLINE_TYPE:
1568  case DLINE_TYPE:
1569  case CRESV_TYPE:
799    default:
800      return NULL;
801    }
# Line 1578 | Line 807 | map_to_list(ConfType type)
807   *              - pointer to name string to find
808   *              - pointer to user
809   *              - pointer to host
810 < *              - optional action to match on as well
811 < * output       - NULL or pointer to found struct MatchItem
810 > *              - optional flags to match on as well
811 > * output       - NULL or pointer to found struct MaskItem
812   * side effects - looks for a match on name field
813   */
814 < struct ConfItem *
815 < find_matching_name_conf(ConfType type, const char *name, const char *user,
816 <                        const char *host, int action)
814 > struct MaskItem *
815 > find_matching_name_conf(enum maskitem_type type, const char *name, const char *user,
816 >                        const char *host, unsigned int flags)
817   {
818    dlink_node *ptr=NULL;
819 <  struct ConfItem *conf=NULL;
1591 <  struct AccessItem *aconf=NULL;
1592 <  struct MatchItem *match_item=NULL;
819 >  struct MaskItem *conf=NULL;
820    dlink_list *list_p = map_to_list(type);
821  
822    switch (type)
823    {
824 < #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:
824 >  case CONF_SERVICE:
825      DLINK_FOREACH(ptr, list_p->head)
826      {
827        conf = ptr->data;
# Line 1618 | Line 833 | find_matching_name_conf(ConfType type, c
833      }
834      break;
835  
836 <  case XLINE_TYPE:
837 <  case ULINE_TYPE:
838 <  case NRESV_TYPE:
836 >  case CONF_XLINE:
837 >  case CONF_ULINE:
838 >  case CONF_NRESV:
839 >  case CONF_CRESV:
840      DLINK_FOREACH(ptr, list_p->head)
841      {
842        conf = ptr->data;
843  
1628      match_item = map_to_conf(conf);
844        if (EmptyString(conf->name))
845 <        continue;
846 <      if ((name != NULL) && match_esc(conf->name, name))
845 >        continue;
846 >      if ((name != NULL) && !match(conf->name, name))
847        {
848 <        if ((user == NULL && (host == NULL)))
849 <          return conf;
850 <        if ((match_item->action & action) != action)
848 >        if ((user == NULL && (host == NULL)))
849 >          return conf;
850 >        if ((conf->flags & flags) != flags)
851            continue;
852 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
853 <          return conf;
854 <        if (match(match_item->user, user) && match(match_item->host, host))
855 <          return conf;
852 >        if (EmptyString(conf->user) || EmptyString(conf->host))
853 >          return conf;
854 >        if (!match(conf->user, user) && !match(conf->host, host))
855 >          return conf;
856        }
857      }
858        break;
859  
860 <  case SERVER_TYPE:
860 >  case CONF_SERVER:
861      DLINK_FOREACH(ptr, list_p->head)
862      {
863        conf = ptr->data;
1649      aconf = map_to_conf(conf);
864  
865 <      if ((name != NULL) && match_esc(name, conf->name))
865 >      if ((name != NULL) && !match(name, conf->name))
866          return conf;
867 <      else if ((host != NULL) && match_esc(host, aconf->host))
867 >      else if ((host != NULL) && !match(host, conf->host))
868          return conf;
869      }
870      break;
871 <  
871 >
872    default:
873      break;
874    }
# Line 1667 | Line 881 | find_matching_name_conf(ConfType type, c
881   *              - pointer to name string to find
882   *              - pointer to user
883   *              - pointer to host
884 < * output       - NULL or pointer to found struct MatchItem
884 > * output       - NULL or pointer to found struct MaskItem
885   * side effects - looks for an exact match on name field
886   */
887 < struct ConfItem *
888 < find_exact_name_conf(ConfType type, const struct Client *who, const char *name,
887 > struct MaskItem *
888 > find_exact_name_conf(enum maskitem_type type, const struct Client *who, const char *name,
889                       const char *user, const char *host)
890   {
891    dlink_node *ptr = NULL;
892 <  struct AccessItem *aconf;
893 <  struct ConfItem *conf;
1680 <  struct MatchItem *match_item;
1681 <  dlink_list *list_p;
1682 <
1683 <  list_p = map_to_list(type);
892 >  struct MaskItem *conf;
893 >  dlink_list *list_p = map_to_list(type);
894  
895    switch(type)
896    {
897 <  case RXLINE_TYPE:
898 <  case XLINE_TYPE:
899 <  case ULINE_TYPE:
900 <  case NRESV_TYPE:
897 >  case CONF_XLINE:
898 >  case CONF_ULINE:
899 >  case CONF_NRESV:
900 >  case CONF_CRESV:
901  
902      DLINK_FOREACH(ptr, list_p->head)
903      {
904        conf = ptr->data;
905 <      match_item = (struct MatchItem *)map_to_conf(conf);
905 >
906        if (EmptyString(conf->name))
907 <        continue;
908 <    
907 >        continue;
908 >
909        if (irccmp(conf->name, name) == 0)
910        {
911 <        if ((user == NULL && (host == NULL)))
912 <          return (conf);
913 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
914 <          return (conf);
915 <        if (match(match_item->user, user) && match(match_item->host, host))
916 <          return (conf);
911 >        if ((user == NULL && (host == NULL)))
912 >          return conf;
913 >        if (EmptyString(conf->user) || EmptyString(conf->host))
914 >          return conf;
915 >        if (!match(conf->user, user) && !match(conf->host, host))
916 >          return conf;
917        }
918      }
919      break;
920  
921 <  case OPER_TYPE:
921 >  case CONF_OPER:
922      DLINK_FOREACH(ptr, list_p->head)
923      {
924        conf = ptr->data;
1715      aconf = map_to_conf(conf);
925  
926        if (EmptyString(conf->name))
927          continue;
# Line 1721 | Line 930 | find_exact_name_conf(ConfType type, cons
930        {
931          if (!who)
932            return conf;
933 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
934 <          return conf;
935 <        if (match(aconf->user, who->username))
933 >        if (EmptyString(conf->user) || EmptyString(conf->host))
934 >          return NULL;
935 >        if (!match(conf->user, who->username))
936          {
937 <          switch (aconf->type)
937 >          switch (conf->htype)
938            {
939              case HM_HOST:
940 <              if (match(aconf->host, who->host) || match(aconf->host, who->sockhost))
941 <                return conf;
940 >              if (!match(conf->host, who->host) || !match(conf->host, who->sockhost))
941 >                if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
942 >                  return conf;
943                break;
944              case HM_IPV4:
945                if (who->localClient->aftype == AF_INET)
946 <                if (match_ipv4(&who->localClient->ip, &aconf->ipnum, aconf->bits))
947 <                  return conf;
946 >                if (match_ipv4(&who->localClient->ip, &conf->addr, conf->bits))
947 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
948 >                    return conf;
949                break;
950   #ifdef IPV6
951              case HM_IPV6:
952                if (who->localClient->aftype == AF_INET6)
953 <                if (match_ipv6(&who->localClient->ip, &aconf->ipnum, aconf->bits))
954 <                  return conf;
953 >                if (match_ipv6(&who->localClient->ip, &conf->addr, conf->bits))
954 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
955 >                    return conf;
956                break;
957   #endif
958              default:
# Line 1752 | Line 964 | find_exact_name_conf(ConfType type, cons
964  
965      break;
966  
967 <  case SERVER_TYPE:
967 >  case CONF_SERVER:
968      DLINK_FOREACH(ptr, list_p->head)
969      {
970        conf = ptr->data;
971 <      aconf = (struct AccessItem *)map_to_conf(conf);
971 >
972        if (EmptyString(conf->name))
973 <        continue;
974 <    
973 >        continue;
974 >
975        if (name == NULL)
976        {
977 <        if (EmptyString(aconf->host))
978 <          continue;
979 <        if (irccmp(aconf->host, host) == 0)
980 <          return(conf);
977 >        if (EmptyString(conf->host))
978 >          continue;
979 >        if (irccmp(conf->host, host) == 0)
980 >          return conf;
981        }
982        else if (irccmp(conf->name, name) == 0)
983 <      {
1772 <          return (conf);
1773 <      }
983 >        return conf;
984      }
1775    break;
985  
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    }
986      break;
987  
988    default:
989      break;
990    }
991 <  return(NULL);
991 >
992 >  return NULL;
993   }
994  
995   /* rehash()
# Line 1801 | Line 1001 | find_exact_name_conf(ConfType type, cons
1001   int
1002   rehash(int sig)
1003   {
1004 <  if (sig != 0)
1005 <    sendto_realops_flags(UMODE_ALL, L_ALL,
1006 <                         "Got signal SIGHUP, reloading ircd.conf file");
1004 >  if (sig)
1005 >    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1006 >                         "Got signal SIGHUP, reloading configuration file(s)");
1007  
1008    restart_resolver();
1009  
# Line 1814 | Line 1014 | rehash(int sig)
1014  
1015    read_conf_files(0);
1016  
1017 <  if (ServerInfo.description != NULL)
1017 >  if (ServerInfo.description)
1018      strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1019  
1020    load_conf_modules();
1021 +  check_conf_klines();
1022  
1023 <  flush_deleted_I_P();
1823 <
1824 <  rehashed_klines = 1;
1825 < /* XXX */
1826 <  if (ConfigLoggingEntry.use_logging)
1827 <    log_close_all();
1828 <
1829 <  return(0);
1023 >  return 0;
1024   }
1025  
1026   /* set_default_conf()
# Line 1844 | Line 1038 | set_default_conf(void)
1038    /* verify init_class() ran, this should be an unnecessary check
1039     * but its not much work.
1040     */
1041 <  assert(class_default == (struct ConfItem *) class_items.tail->data);
1041 >  assert(class_default == class_get_list()->tail->data);
1042  
1043   #ifdef HAVE_LIBCRYPTO
1044 +  ServerInfo.message_digest_algorithm = EVP_sha256();
1045    ServerInfo.rsa_private_key = NULL;
1046    ServerInfo.rsa_private_key_file = NULL;
1047   #endif
# Line 1854 | Line 1049 | set_default_conf(void)
1049    /* ServerInfo.name is not rehashable */
1050    /* ServerInfo.name = ServerInfo.name; */
1051    ServerInfo.description = NULL;
1052 <  DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1053 <  DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1052 >  ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1053 >  ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1054  
1055    memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1056    ServerInfo.specific_ipv4_vhost = 0;
# Line 1863 | Line 1058 | set_default_conf(void)
1058    ServerInfo.specific_ipv6_vhost = 0;
1059  
1060    ServerInfo.max_clients = MAXCLIENTS_MAX;
1061 <
1061 >  ServerInfo.max_nick_length = 9;
1062 >  ServerInfo.max_topic_length = 80;
1063    ServerInfo.hub = 0;
1064    ServerInfo.dns_host.sin_addr.s_addr = 0;
1065    ServerInfo.dns_host.sin_port = 0;
1066 +
1067    AdminInfo.name = NULL;
1068    AdminInfo.email = NULL;
1069    AdminInfo.description = NULL;
1070  
1071 <  log_close_all();
1071 >  log_del_all();
1072  
1073    ConfigLoggingEntry.use_logging = 1;
1074  
1075    ConfigChannel.disable_fake_channels = 0;
1076 <  ConfigChannel.restrict_channels = 0;
1077 <  ConfigChannel.disable_local_channels = 0;
1078 <  ConfigChannel.use_invex = 1;
1079 <  ConfigChannel.use_except = 1;
1883 <  ConfigChannel.use_knock = 1;
1884 <  ConfigChannel.knock_delay = 300;
1076 >  ConfigChannel.invite_client_count = 10;
1077 >  ConfigChannel.invite_client_time = 300;
1078 >  ConfigChannel.knock_client_count = 1;
1079 >  ConfigChannel.knock_client_time = 300;
1080    ConfigChannel.knock_delay_channel = 60;
1081 <  ConfigChannel.max_chans_per_user = 15;
1887 <  ConfigChannel.quiet_on_ban = 1;
1081 >  ConfigChannel.max_channels = 25;
1082    ConfigChannel.max_bans = 25;
1083    ConfigChannel.default_split_user_count = 0;
1084    ConfigChannel.default_split_server_count = 0;
1085    ConfigChannel.no_join_on_split = 0;
1086    ConfigChannel.no_create_on_split = 0;
1893  ConfigChannel.burst_topicwho = 1;
1087  
1088    ConfigServerHide.flatten_links = 0;
1089    ConfigServerHide.links_delay = 300;
1090    ConfigServerHide.hidden = 0;
1898  ConfigServerHide.disable_hidden = 0;
1091    ConfigServerHide.hide_servers = 0;
1092 <  DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1092 >  ConfigServerHide.hide_services = 0;
1093 >  ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
1094    ConfigServerHide.hide_server_ips = 0;
1095 +  ConfigServerHide.disable_remote_commands = 0;
1096  
1097 <  
1098 <  DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1097 >  ConfigFileEntry.away_count = 2;
1098 >  ConfigFileEntry.away_time = 10;
1099 >  ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1100    ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1101 +  ConfigFileEntry.cycle_on_host_change = 1;
1102 +  ConfigFileEntry.glines = 0;
1103 +  ConfigFileEntry.gline_time = 12 * 3600;
1104 +  ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
1105    ConfigFileEntry.gline_min_cidr = 16;
1106    ConfigFileEntry.gline_min_cidr6 = 48;
1107    ConfigFileEntry.invisible_on_connect = 1;
1909  ConfigFileEntry.burst_away = 0;
1910  ConfigFileEntry.use_whois_actually = 1;
1108    ConfigFileEntry.tkline_expire_notices = 1;
1109    ConfigFileEntry.hide_spoof_ips = 1;
1110    ConfigFileEntry.ignore_bogus_ts = 0;
1111    ConfigFileEntry.disable_auth = 0;
1915  ConfigFileEntry.disable_remote = 0;
1112    ConfigFileEntry.kill_chase_time_limit = 90;
1113    ConfigFileEntry.default_floodcount = 8;
1114    ConfigFileEntry.failed_oper_notice = 1;
# Line 1926 | Line 1122 | set_default_conf(void)
1122    ConfigFileEntry.anti_spam_exit_message_time = 0;
1123    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1124    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1125 <  ConfigFileEntry.kline_with_reason = 1;
1126 <  ConfigFileEntry.kline_reason = NULL;
1931 <  ConfigFileEntry.warn_no_nline = 1;
1125 >  ConfigFileEntry.warn_no_connect_block = 1;
1126 >  ConfigFileEntry.stats_e_disabled = 0;
1127    ConfigFileEntry.stats_o_oper_only = 0;
1128 <  ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
1129 <  ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
1128 >  ConfigFileEntry.stats_k_oper_only = 1;  /* 1 = masked */
1129 >  ConfigFileEntry.stats_i_oper_only = 1;  /* 1 = masked */
1130    ConfigFileEntry.stats_P_oper_only = 0;
1131 +  ConfigFileEntry.stats_u_oper_only = 0;
1132    ConfigFileEntry.caller_id_wait = 60;
1133    ConfigFileEntry.opers_bypass_callerid = 0;
1134    ConfigFileEntry.pace_wait = 10;
# Line 1942 | Line 1138 | set_default_conf(void)
1138    ConfigFileEntry.no_oper_flood = 0;
1139    ConfigFileEntry.true_no_oper_flood = 0;
1140    ConfigFileEntry.oper_pass_resv = 1;
1945  ConfigFileEntry.glines = 0;
1946  ConfigFileEntry.gline_time = 12 * 3600;
1141    ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1948  ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1142    ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1143 <  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1144 <    UMODE_OPERWALL | UMODE_WALLOP;
1145 <  ConfigFileEntry.use_egd = 0;
1953 <  ConfigFileEntry.egdpool_path = NULL;
1954 <  ConfigFileEntry.throttle_time = 10;
1955 < }
1956 <
1957 < /* read_conf()
1958 < *
1959 < * inputs       - file descriptor pointing to config file to use
1960 < * output       - None
1961 < * side effects - Read configuration file.
1962 < */
1963 < static void
1964 < read_conf(FILE *file)
1965 < {
1966 <  lineno = 0;
1967 <
1968 <  set_default_conf(); /* Set default values prior to conf parsing */
1969 <  conf_parser_ctx.pass = 1;
1970 <  yyparse();          /* pick up the classes first */
1971 <
1972 <  rewind(file);
1973 <
1974 <  conf_parser_ctx.pass = 2;
1975 <  yyparse();          /* Load the values from the conf */
1976 <  validate_conf();    /* Check to make sure some values are still okay. */
1977 <                      /* Some global values are also loaded here. */
1978 <  check_class();      /* Make sure classes are valid */
1143 >  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE | UMODE_WALLOP;
1144 >  ConfigFileEntry.throttle_count = 1;
1145 >  ConfigFileEntry.throttle_time = 1;
1146   }
1147  
1148   static void
# Line 1988 | Line 1155 | validate_conf(void)
1155      ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1156  
1157    if (ServerInfo.network_name == NULL)
1158 <    DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1158 >    ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1159  
1160    if (ServerInfo.network_desc == NULL)
1161 <    DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1161 >    ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1162  
1163    if (ConfigFileEntry.service_name == NULL)
1164 <    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;
1164 >    ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1165  
1166    ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1167   }
1168  
1169 < /* lookup_confhost()
1169 > /* read_conf()
1170   *
1171 < * start DNS lookups of all hostnames in the conf
1172 < * line and convert an IP addresses in a.b.c.d number for to IP#s.
1171 > * inputs       - file descriptor pointing to config file to use
1172 > * output       - None
1173 > * side effects - Read configuration file.
1174   */
1175   static void
1176 < lookup_confhost(struct ConfItem *conf)
1176 > read_conf(FILE *file)
1177   {
1178 <  struct AccessItem *aconf;
2015 <  struct addrinfo hints, *res;
1178 >  lineno = 0;
1179  
1180 <  aconf = map_to_conf(conf);
1180 >  set_default_conf();  /* Set default values prior to conf parsing */
1181 >  conf_parser_ctx.pass = 1;
1182 >  yyparse();  /* Pick up the classes first */
1183  
1184 <  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 <  }
1184 >  rewind(file);
1185  
1186 <  if (strchr(aconf->host, '*') ||
1187 <      strchr(aconf->host, '?'))
1188 <    return;
1186 >  conf_parser_ctx.pass = 2;
1187 >  yyparse();  /* Load the values from the conf */
1188 >  validate_conf();  /* Check to make sure some values are still okay. */
1189 >                    /* Some global values are also loaded here. */
1190 >  class_delete_marked();  /* Delete unused classes that are marked for deletion */
1191 > }
1192 >
1193 > /* lookup_confhost()
1194 > *
1195 > * start DNS lookups of all hostnames in the conf
1196 > * line and convert an IP addresses in a.b.c.d number for to IP#s.
1197 > */
1198 > void
1199 > lookup_confhost(struct MaskItem *conf)
1200 > {
1201 >  struct addrinfo hints, *res;
1202  
1203 <  /* Do name lookup now on hostnames given and store the
1203 >  /*
1204 >   * Do name lookup now on hostnames given and store the
1205     * ip numbers in conf structure.
1206     */
1207    memset(&hints, 0, sizeof(hints));
# Line 2039 | Line 1212 | lookup_confhost(struct ConfItem *conf)
1212    /* Get us ready for a bind() and don't bother doing dns lookup */
1213    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1214  
1215 <  if (getaddrinfo(aconf->host, NULL, &hints, &res))
1215 >  if (getaddrinfo(conf->host, NULL, &hints, &res))
1216    {
1217 <    conf_dns_lookup(aconf);
1217 >    conf_dns_lookup(conf);
1218      return;
1219    }
1220  
1221 <  assert(res != NULL);
1221 >  assert(res);
1222 >
1223 >  memcpy(&conf->addr, res->ai_addr, res->ai_addrlen);
1224 >  conf->addr.ss_len = res->ai_addrlen;
1225 >  conf->addr.ss.ss_family = res->ai_family;
1226  
2050  memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
2051  aconf->ipnum.ss_len = res->ai_addrlen;
2052  aconf->ipnum.ss.ss_family = res->ai_family;
1227    freeaddrinfo(res);
1228   }
1229  
# Line 2063 | Line 1237 | lookup_confhost(struct ConfItem *conf)
1237   int
1238   conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1239   {
1240 <  struct ip_entry *ip_found;
1241 <  struct AccessItem *aconf = find_dline_conf(addr, aftype);
1240 >  struct ip_entry *ip_found = NULL;
1241 >  struct MaskItem *conf = find_dline_conf(addr, aftype);
1242  
1243    /* DLINE exempt also gets you out of static limits/pacing... */
1244 <  if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1244 >  if (conf && (conf->type == CONF_EXEMPT))
1245      return 0;
1246  
1247 <  if (aconf != NULL)
1247 >  if (conf)
1248      return BANNED_CLIENT;
1249  
1250    ip_found = find_or_add_ip(addr);
1251  
1252 <  if ((CurrentTime - ip_found->last_attempt) <
2079 <      ConfigFileEntry.throttle_time)
1252 >  if ((CurrentTime - ip_found->last_attempt) < ConfigFileEntry.throttle_time)
1253    {
1254 <    ip_found->last_attempt = CurrentTime;
1255 <    return TOO_FAST;
1254 >    if (ip_found->connection_count >= ConfigFileEntry.throttle_count)
1255 >      return TOO_FAST;
1256 >
1257 >    ++ip_found->connection_count;
1258    }
1259 +  else
1260 +    ip_found->connection_count = 1;
1261  
1262    ip_found->last_attempt = CurrentTime;
1263    return 0;
1264   }
1265  
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
2111 /* find_kill()
2112 *
2113 * inputs       - pointer to client structure
2114 * output       - pointer to struct AccessItem if found
2115 * side effects - See if this user is klined already,
2116 *                and if so, return struct AccessItem pointer
2117 */
2118 struct AccessItem *
2119 find_kill(struct Client *client_p)
2120 {
2121  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;
2127
2128  assert(client_p != NULL);
2129
2130  aconf = find_kline_conf(client_p->host, client_p->username,
2131                          &client_p->localClient->ip,
2132                          client_p->localClient->aftype);
2133  if (aconf == NULL)
2134    aconf = find_regexp_kline(uhi);
2135
2136  if (aconf && (aconf->status & CONF_KLINE))
2137    return aconf;
2138
2139  return NULL;
2140 }
2141
2142 struct AccessItem *
2143 find_gline(struct Client *client_p)
2144 {
2145  struct AccessItem *aconf;
2146
2147  assert(client_p != NULL);
2148
2149  aconf = find_gline_conf(client_p->host, client_p->username,
2150                          &client_p->localClient->ip,
2151                          client_p->localClient->aftype);
2152
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  }
2214 }
2215
1266   /* cleanup_tklines()
1267   *
1268   * inputs       - NONE
# Line 2223 | Line 1273 | add_temp_line(struct ConfItem *conf)
1273   void
1274   cleanup_tklines(void *notused)
1275   {
1276 <  expire_tklines(&temporary_glines);
1277 <  expire_tklines(&temporary_klines);
1278 <  expire_tklines(&temporary_dlines);
1279 <  expire_tklines(&temporary_xlines);
2230 <  expire_tklines(&temporary_rxlines);
2231 <  expire_tklines(&temporary_rklines);
2232 <  expire_tklines(&temporary_resv);
1276 >  hostmask_expire_temporary();
1277 >  expire_tklines(&xconf_items);
1278 >  expire_tklines(&nresv_items);
1279 >  expire_tklines(&cresv_items);
1280   }
1281  
1282   /* expire_tklines()
# Line 2241 | Line 1288 | cleanup_tklines(void *notused)
1288   static void
1289   expire_tklines(dlink_list *tklist)
1290   {
1291 <  dlink_node *ptr;
1292 <  dlink_node *next_ptr;
2246 <  struct ConfItem *conf;
2247 <  struct MatchItem *xconf;
2248 <  struct MatchItem *nconf;
2249 <  struct AccessItem *aconf;
2250 <  struct ResvChannel *cconf;
1291 >  dlink_node *ptr = NULL, *ptr_next = NULL;
1292 >  struct MaskItem *conf = NULL;
1293  
1294 <  DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
1294 >  DLINK_FOREACH_SAFE(ptr, ptr_next, tklist->head)
1295    {
1296      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        }
1297  
1298 <        dlinkDelete(ptr, tklist);
1299 <        delete_one_address_conf(aconf->host, aconf);
1300 <      }
1301 <    }
2285 <    else if (conf->type == XLINE_TYPE ||
2286 <             conf->type == RXLINE_TYPE)
1298 >    if (!conf->until || conf->until > CurrentTime)
1299 >      continue;
1300 >
1301 >    if (conf->type == CONF_XLINE)
1302      {
1303 <      xconf = (struct MatchItem *)map_to_conf(conf);
1304 <      if (xconf->hold <= CurrentTime)
1305 <      {
1306 <        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 <      }
1303 >      if (ConfigFileEntry.tkline_expire_notices)
1304 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1305 >                               "Temporary X-line for [%s] expired", conf->name);
1306 >      conf_free(conf);
1307      }
1308 <    else if (conf->type == RKLINE_TYPE)
1308 >    else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1309      {
1310 <      aconf = map_to_conf(conf);
1311 <      if (aconf->hold <= CurrentTime)
2304 <      {
2305 <        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 <      }
2314 <    }
2315 <    else if (conf->type == NRESV_TYPE)
2316 <    {
2317 <      nconf = (struct MatchItem *)map_to_conf(conf);
2318 <      if (nconf->hold <= CurrentTime)
2319 <      {
2320 <        if (ConfigFileEntry.tkline_expire_notices)
2321 <          sendto_realops_flags(UMODE_ALL, L_ALL,
1310 >      if (ConfigFileEntry.tkline_expire_notices)
1311 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1312                                 "Temporary RESV for [%s] expired", conf->name);
1313 <        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 <      }
1313 >      conf_free(conf);
1314      }
1315    }
1316   }
# Line 2347 | Line 1323 | expire_tklines(dlink_list *tklist)
1323   */
1324   static const struct oper_privs
1325   {
1326 <  const unsigned int oprivs;
1326 >  const unsigned int flag;
1327    const unsigned char c;
1328   } flag_list[] = {
1329 <  { OPER_FLAG_ADMIN,       'A' },
1330 <  { OPER_FLAG_REMOTEBAN,   'B' },
1331 <  { OPER_FLAG_DIE,         'D' },
1332 <  { OPER_FLAG_GLINE,       'G' },
1333 <  { OPER_FLAG_REHASH,      'H' },
1334 <  { OPER_FLAG_K,           'K' },
1335 <  { OPER_FLAG_OPERWALL,    'L' },
1336 <  { OPER_FLAG_N,           'N' },
1337 <  { OPER_FLAG_GLOBAL_KILL, 'O' },
1338 <  { OPER_FLAG_REMOTE,      'R' },
1339 <  { OPER_FLAG_OPER_SPY,    'S' },
1340 <  { OPER_FLAG_UNKLINE,     'U' },
1341 <  { OPER_FLAG_X,           'X' },
1329 >  { OPER_FLAG_ADMIN,          'A' },
1330 >  { OPER_FLAG_REMOTEBAN,      'B' },
1331 >  { OPER_FLAG_DIE,            'D' },
1332 >  { OPER_FLAG_GLINE,          'G' },
1333 >  { OPER_FLAG_REHASH,         'H' },
1334 >  { OPER_FLAG_KLINE,          'K' },
1335 >  { OPER_FLAG_KILL,           'N' },
1336 >  { OPER_FLAG_KILL_REMOTE,    'O' },
1337 >  { OPER_FLAG_CONNECT,        'P' },
1338 >  { OPER_FLAG_CONNECT_REMOTE, 'Q' },
1339 >  { OPER_FLAG_SQUIT,          'R' },
1340 >  { OPER_FLAG_SQUIT_REMOTE,   'S' },
1341 >  { OPER_FLAG_UNKLINE,        'U' },
1342 >  { OPER_FLAG_XLINE,          'X' },
1343    { 0, '\0' }
1344   };
1345  
1346   char *
1347   oper_privs_as_string(const unsigned int port)
1348   {
1349 <  static char privs_out[16];
1349 >  static char privs_out[IRCD_BUFSIZE];
1350    char *privs_ptr = privs_out;
2374  unsigned int i = 0;
1351  
1352 <  for (; flag_list[i].oprivs; ++i)
1352 >  for (const struct oper_privs *opriv = flag_list; opriv->flag; ++opriv)
1353    {
1354 <    if (port & flag_list[i].oprivs)
1355 <      *privs_ptr++ = flag_list[i].c;
1354 >    if (port & opriv->flag)
1355 >      *privs_ptr++ = opriv->c;
1356      else
1357 <      *privs_ptr++ = ToLowerTab[flag_list[i].c];
1357 >      *privs_ptr++ = ToLower(opriv->c);
1358    }
1359  
1360    *privs_ptr = '\0';
# Line 2387 | Line 1363 | oper_privs_as_string(const unsigned int
1363   }
1364  
1365   /*
1366 < * Input: A client to find the active oper{} name for.
1366 > * Input: A client to find the active operator {} name for.
1367   * Output: The nick!user@host{oper} of the oper.
1368   *         "oper" is server name for remote opers
1369   * Side effects: None.
1370   */
1371 < char *
1371 > const char *
1372   get_oper_name(const struct Client *client_p)
1373   {
1374 <  dlink_node *cnode;
2399 <  struct ConfItem *conf;
2400 <  struct AccessItem *aconf;
2401 <
1374 >  const dlink_node *cnode = NULL;
1375    /* +5 for !,@,{,} and null */
1376    static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
1377  
1378    if (MyConnect(client_p))
1379    {
1380 <    DLINK_FOREACH(cnode, client_p->localClient->confs.head)
1380 >    if ((cnode = client_p->localClient->confs.head))
1381      {
1382 <      conf = cnode->data;
2410 <      aconf = map_to_conf(conf);
1382 >      const struct MaskItem *conf = cnode->data;
1383  
1384 <      if (IsConfOperator(aconf))
1384 >      if (IsConfOperator(conf))
1385        {
1386 <        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1386 >        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1387                   client_p->username, client_p->host, conf->name);
1388 <        return buffer;
1388 >        return buffer;
1389        }
1390      }
1391  
1392 <    /* Probably should assert here for now. If there is an oper out there
1393 <     * with no oper{} conf attached, it would be good for us to know...
1392 >    /*
1393 >     * Probably should assert here for now. If there is an oper out there
1394 >     * with no operator {} conf attached, it would be good for us to know...
1395       */
1396 <    assert(0); /* Oper without oper conf! */
1396 >    assert(0);  /* Oper without oper conf! */
1397    }
1398  
1399    snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1400 <           client_p->username, client_p->host, client_p->servptr->name);
1400 >           client_p->username, client_p->host, client_p->servptr->name);
1401    return buffer;
1402   }
1403  
# Line 2437 | Line 1410 | get_oper_name(const struct Client *clien
1410   void
1411   read_conf_files(int cold)
1412   {
1413 <  const char *filename;
1414 <  char chanmodes[32];
1415 <  char chanlimit[32];
1413 >  const char *filename = NULL;
1414 >  char chanmodes[IRCD_BUFSIZE] = "";
1415 >  char chanlimit[IRCD_BUFSIZE] = "";
1416  
1417    conf_parser_ctx.boot = cold;
1418 <  filename = get_conf_name(CONF_TYPE);
1418 >  filename = ConfigFileEntry.configfile;
1419  
1420    /* We need to know the initial filename for the yyerror() to report
1421       FIXME: The full path is in conffilenamebuf first time since we
1422 <             dont know anything else
1422 >             don't know anything else
1423  
1424 <     - Gozem 2002-07-21
1424 >     - Gozem 2002-07-21
1425    */
1426    strlcpy(conffilebuf, filename, sizeof(conffilebuf));
1427  
# Line 2462 | Line 1435 | read_conf_files(int cold)
1435      }
1436      else
1437      {
1438 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1439 <                           "Unable to read configuration file '%s': %s",
1440 <                           filename, strerror(errno));
1438 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1439 >                           "Unable to read configuration file '%s': %s",
1440 >                           filename, strerror(errno));
1441        return;
1442      }
1443    }
# Line 2475 | Line 1448 | read_conf_files(int cold)
1448    read_conf(conf_parser_ctx.conf_file);
1449    fclose(conf_parser_ctx.conf_file);
1450  
1451 +  log_reopen_all();
1452 +
1453 +  add_isupport("NICKLEN", NULL, ServerInfo.max_nick_length);
1454    add_isupport("NETWORK", ServerInfo.network_name, -1);
1455 <  snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
1456 <           ConfigChannel.use_except ? "e" : "",
2481 <           ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
1455 >
1456 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1457    add_isupport("MAXLIST", chanmodes, -1);
1458    add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1459 +  add_isupport("CHANTYPES", "#", -1);
1460  
1461 <  if (ConfigChannel.disable_local_channels)
1462 <    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);
1461 >  snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1462 >           ConfigChannel.max_channels);
1463    add_isupport("CHANLIMIT", chanlimit, -1);
1464 <  snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
1465 <           ConfigChannel.use_except ? "e" : "",
1466 <           ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
2497 <  add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2498 <
2499 <  if (ConfigChannel.use_except)
2500 <    add_isupport("EXCEPTS", "e", -1);
2501 <  if (ConfigChannel.use_invex)
2502 <    add_isupport("INVEX", "I", -1);
1464 >  snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,cimnprstMORS");
1465 >  add_isupport("CHANNELLEN", NULL, CHANNELLEN);
1466 >  add_isupport("TOPICLEN", NULL, ServerInfo.max_topic_length);
1467    add_isupport("CHANMODES", chanmodes, -1);
1468  
1469    /*
# Line 2507 | Line 1471 | read_conf_files(int cold)
1471     * on strlen(form_str(RPL_ISUPPORT))
1472     */
1473    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  }
1474   }
1475  
1476   /* clear_out_old_conf()
# Line 2558 | Line 1483 | static void
1483   clear_out_old_conf(void)
1484   {
1485    dlink_node *ptr = NULL, *next_ptr = NULL;
1486 <  struct ConfItem *conf;
2562 <  struct AccessItem *aconf;
2563 <  struct ClassItem *cltmp;
2564 <  struct MatchItem *match_item;
1486 >  struct MaskItem *conf;
1487    dlink_list *free_items [] = {
1488 <    &server_items,   &oconf_items,    &hub_items, &leaf_items,
1489 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1490 <     &nresv_items, &cluster_items,  &gdeny_items, &service_items, NULL
1488 >    &server_items,   &oconf_items,
1489 >     &uconf_items,   &xconf_items,
1490 >     &nresv_items, &cluster_items,  &service_items, &cresv_items, NULL
1491    };
1492  
1493    dlink_list ** iterator = free_items; /* C is dumb */
# Line 2573 | Line 1495 | clear_out_old_conf(void)
1495    /* We only need to free anything allocated by yyparse() here.
1496     * Resetting structs, etc, is taken care of by set_default_conf().
1497     */
1498 <  
1498 >
1499    for (; *iterator != NULL; iterator++)
1500    {
1501      DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1502      {
1503        conf = ptr->data;
2582      /* XXX This is less than pretty */
2583      if (conf->type == SERVER_TYPE)
2584      {
2585        aconf = map_to_conf(conf);
1504  
1505 <        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);
1505 >      dlinkDelete(&conf->node, map_to_list(conf->type));
1506  
1507 <        if (aconf->clients != 0)
1508 <        {
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)
1507 >      /* XXX This is less than pretty */
1508 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1509        {
1510 <        aconf = map_to_conf(conf);
1511 <
2615 <        if (aconf->clients != 0)
2616 <        {
2617 <          SetConfIllegal(aconf);
2618 <        }
2619 <        else
2620 <        {
2621 <          delete_conf_item(conf);
2622 <        }
1510 >        if (!conf->ref_count)
1511 >          conf_free(conf);
1512        }
1513 <      else if (conf->type == XLINE_TYPE  ||
2625 <               conf->type == RXLINE_TYPE ||
2626 <               conf->type == RKLINE_TYPE)
1513 >      else if (conf->type == CONF_XLINE)
1514        {
1515 <        /* temporary (r)xlines are also on
1516 <         * the (r)xconf items list */
2630 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2631 <          continue;
2632 <
2633 <        delete_conf_item(conf);
1515 >        if (!conf->until)
1516 >          conf_free(conf);
1517        }
1518        else
1519 <      {
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 <      }
1519 >        conf_free(conf);
1520      }
1521    }
1522  
1523 +  motd_clear();
1524 +
1525    /*
1526     * don't delete the class table, rather mark all entries
1527 <   * for deletion. The table is cleaned up by check_class. - avalon
1527 >   * for deletion. The table is cleaned up by class_delete_marked. - avalon
1528     */
1529 <  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 <  }
1529 >  class_mark_for_deletion();
1530  
1531    clear_out_address_conf();
1532  
# Line 2675 | Line 1540 | clear_out_old_conf(void)
1540    ServerInfo.network_name = NULL;
1541    MyFree(ServerInfo.network_desc);
1542    ServerInfo.network_desc = NULL;
2678  MyFree(ConfigFileEntry.egdpool_path);
2679  ConfigFileEntry.egdpool_path = NULL;
1543   #ifdef HAVE_LIBCRYPTO
1544 <  if (ServerInfo.rsa_private_key != NULL)
1544 >  if (ServerInfo.rsa_private_key)
1545    {
1546      RSA_free(ServerInfo.rsa_private_key);
1547      ServerInfo.rsa_private_key = NULL;
# Line 2686 | Line 1549 | clear_out_old_conf(void)
1549  
1550    MyFree(ServerInfo.rsa_private_key_file);
1551    ServerInfo.rsa_private_key_file = NULL;
2689
2690  if (ServerInfo.server_ctx)
2691    SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
2692                                               SSL_OP_NO_SSLv3|
2693                                               SSL_OP_NO_TLSv1);
2694  if (ServerInfo.client_ctx)
2695    SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
2696                                               SSL_OP_NO_SSLv3|
2697                                               SSL_OP_NO_TLSv1);
1552   #endif
1553  
2700  /* clean out old resvs from the conf */
2701  clear_conf_resv();
2702
1554    /* clean out AdminInfo */
1555    MyFree(AdminInfo.name);
1556    AdminInfo.name = NULL;
# Line 2708 | Line 1559 | clear_out_old_conf(void)
1559    MyFree(AdminInfo.description);
1560    AdminInfo.description = NULL;
1561  
2711  /* operator{} and class{} blocks are freed above */
1562    /* clean out listeners */
1563    close_listeners();
1564  
2715  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2716   * exempt{} and gecos{} blocks are freed above too
2717   */
2718
1565    /* clean out general */
1566    MyFree(ConfigFileEntry.service_name);
1567    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;
1568   }
1569  
1570   /* conf_add_class_to_conf()
1571   *
1572   * inputs       - pointer to config item
1573   * output       - NONE
1574 < * side effects - Add a class pointer to a conf
1574 > * side effects - Add a class pointer to a conf
1575   */
1576   void
1577 < conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
1577 > conf_add_class_to_conf(struct MaskItem *conf, const char *class_name)
1578   {
1579 <  struct AccessItem *aconf = map_to_conf(conf);
3020 <  struct ClassItem *class = NULL;
3021 <
3022 <  if (class_name == NULL)
1579 >  if (class_name == NULL)
1580    {
1581 <    aconf->class_ptr = class_default;
1581 >    conf->class = class_default;
1582  
1583 <    if (conf->type == CLIENT_TYPE)
1584 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1585 <                           "Warning *** Defaulting to default class for %s@%s",
1586 <                           aconf->user, aconf->host);
1583 >    if (conf->type == CONF_CLIENT)
1584 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1585 >                           "Warning *** Defaulting to default class for %s@%s",
1586 >                           conf->user, conf->host);
1587      else
1588 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1589 <                           "Warning *** Defaulting to default class for %s",
1590 <                           conf->name);
1588 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1589 >                           "Warning *** Defaulting to default class for %s",
1590 >                           conf->name);
1591    }
1592    else
1593 <    aconf->class_ptr = find_class(class_name);
3037 <
3038 <  if (aconf->class_ptr)
3039 <    class = map_to_conf(aconf->class_ptr);
1593 >    conf->class = class_find(class_name, 1);
1594  
1595 <  if (aconf->class_ptr == NULL || !class->active)
1595 >  if (conf->class == NULL)
1596    {
1597 <    if (conf->type == CLIENT_TYPE)
1598 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1599 <                           "Warning *** Defaulting to default class for %s@%s",
1600 <                           aconf->user, aconf->host);
1597 >    if (conf->type == CONF_CLIENT)
1598 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1599 >                           "Warning *** Defaulting to default class for %s@%s",
1600 >                           conf->user, conf->host);
1601      else
1602 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1603 <                           "Warning *** Defaulting to default class for %s",
1604 <                           conf->name);
1605 <    aconf->class_ptr = class_default;
3052 <  }
3053 < }
3054 <
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;
1602 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1603 >                           "Warning *** Defaulting to default class for %s",
1604 >                           conf->name);
1605 >    conf->class = class_default;
1606    }
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;
1607   }
1608  
1609   /* yyerror()
# Line 3124 | Line 1621 | yyerror(const char *msg)
1621      return;
1622  
1623    strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1624 <  sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
1624 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1625 >                       "\"%s\", line %u: %s: %s",
1626 >                       conffilebuf, lineno + 1, msg, newlinebuf);
1627 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1628 >       conffilebuf, lineno + 1, msg, newlinebuf);
1629 > }
1630 >
1631 > void
1632 > conf_error_report(const char *msg)
1633 > {
1634 >  char newlinebuf[IRCD_BUFSIZE];
1635 >
1636 >  strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1637 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1638 >                       "\"%s\", line %u: %s: %s",
1639                         conffilebuf, lineno + 1, msg, newlinebuf);
1640    ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1641         conffilebuf, lineno + 1, msg, newlinebuf);
# Line 3132 | Line 1643 | yyerror(const char *msg)
1643  
1644   /*
1645   * valid_tkline()
1646 < *
1646 > *
1647   * inputs       - pointer to ascii string to check
1648   *              - whether the specified time is in seconds or minutes
1649   * output       - -1 not enough parameters
# Line 3141 | Line 1652 | yyerror(const char *msg)
1652   * Originally written by Dianora (Diane, db@db.net)
1653   */
1654   time_t
1655 < valid_tkline(const char *p, int minutes)
1655 > valid_tkline(const char *data, const int minutes)
1656   {
1657 +  const unsigned char *p = (const unsigned char *)data;
1658 +  unsigned char tmpch = '\0';
1659    time_t result = 0;
1660  
1661 <  for (; *p; ++p)
1661 >  while ((tmpch = *p++))
1662    {
1663 <    if (!IsDigit(*p))
1663 >    if (!IsDigit(tmpch))
1664        return 0;
1665  
1666      result *= 10;
1667 <    result += ((*p) & 0xF);
1667 >    result += (tmpch & 0xF);
1668    }
1669  
1670    /*
1671 <   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1671 >   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1672     * i.e. they specifically use 0, I am going to return 1 instead
1673     * as a return value of non-zero is used to flag it as a temporary kline
1674     */
1675    if (result == 0)
1676      result = 1;
1677  
1678 <  /*
1678 >  /*
1679     * If the incoming time is in seconds convert it to minutes for the purpose
1680     * of this calculation
1681     */
1682    if (!minutes)
1683 <    result = result / (time_t)60;
1683 >    result = result / 60;
1684  
1685    if (result > MAX_TDKLINE_TIME)
1686      result = MAX_TDKLINE_TIME;
1687  
1688 <  result = result * (time_t)60;  /* turn it into seconds */
1688 >  result = result * 60;  /* turn it into seconds */
1689  
1690    return result;
1691   }
1692  
1693 + /* valid_wild_card_simple()
1694 + *
1695 + * inputs       - data to check for sufficient non-wildcard characters
1696 + * outputs      - 1 if valid, else 0
1697 + * side effects - none
1698 + */
1699 + int
1700 + valid_wild_card_simple(const char *data)
1701 + {
1702 +  const unsigned char *p = (const unsigned char *)data;
1703 +  unsigned char tmpch = '\0';
1704 +  unsigned int nonwild = 0;
1705 +
1706 +  while ((tmpch = *p++))
1707 +  {
1708 +    if (tmpch == '\\' && *p)
1709 +    {
1710 +      ++p;
1711 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1712 +        return 1;
1713 +    }
1714 +    else if (!IsMWildChar(tmpch))
1715 +    {
1716 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1717 +        return 1;
1718 +    }
1719 +  }
1720 +
1721 +  return 0;
1722 + }
1723 +
1724   /* valid_wild_card()
1725   *
1726   * input        - pointer to client
# Line 3188 | Line 1732 | valid_tkline(const char *p, int minutes)
1732   int
1733   valid_wild_card(struct Client *source_p, int warn, int count, ...)
1734   {
1735 <  char *p;
1736 <  char tmpch;
3193 <  int nonwild = 0;
1735 >  unsigned char tmpch = '\0';
1736 >  unsigned int nonwild = 0;
1737    va_list args;
1738  
1739    /*
# Line 3209 | Line 1752 | valid_wild_card(struct Client *source_p,
1752  
1753    while (count--)
1754    {
1755 <    p = va_arg(args, char *);
1755 >    const unsigned char *p = va_arg(args, const unsigned char *);
1756      if (p == NULL)
1757        continue;
1758  
# Line 3222 | Line 1765 | valid_wild_card(struct Client *source_p,
1765           * break - no point in searching further.
1766           */
1767          if (++nonwild >= ConfigFileEntry.min_nonwildcard)
1768 +        {
1769 +          va_end(args);
1770            return 1;
1771 +        }
1772        }
1773      }
1774    }
1775  
1776    if (warn)
1777 <    sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
1778 <               me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
1777 >    sendto_one_notice(source_p, &me,
1778 >                      ":Please include at least %u non-wildcard characters with the mask",
1779 >                      ConfigFileEntry.min_nonwildcard);
1780 >  va_end(args);
1781    return 0;
1782   }
1783  
# Line 3243 | Line 1791 | valid_wild_card(struct Client *source_p,
1791   *              - parse_flags bit map of things to test
1792   *              - pointer to user or string to parse into
1793   *              - pointer to host or NULL to parse into if non NULL
1794 < *              - pointer to optional tkline time or NULL
1794 > *              - pointer to optional tkline time or NULL
1795   *              - pointer to target_server to parse into if non NULL
1796   *              - pointer to reason to parse into
1797   *
# Line 3265 | Line 1813 | valid_wild_card(struct Client *source_p,
1813   */
1814   int
1815   parse_aline(const char *cmd, struct Client *source_p,
1816 <            int parc, char **parv,
1817 <            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1818 <            char **target_server, char **reason)
1816 >            int parc, char **parv,
1817 >            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1818 >            char **target_server, char **reason)
1819   {
1820    int found_tkline_time=0;
1821 <  static char def_reason[] = "No Reason";
1821 >  static char def_reason[] = CONF_NOREASON;
1822    static char user[USERLEN*4+1];
1823    static char host[HOSTLEN*4+1];
1824  
# Line 3288 | Line 1836 | parse_aline(const char *cmd, struct Clie
1836        *tkline_time = found_tkline_time;
1837      else
1838      {
1839 <      sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3292 <                 me.name, source_p->name, cmd);
1839 >      sendto_one_notice(source_p, &me, ":temp_line not supported by %s", cmd);
1840        return -1;
1841      }
1842    }
1843  
1844    if (parc == 0)
1845    {
1846 <    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3300 <               me.name, source_p->name, cmd);
1846 >    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1847      return -1;
1848    }
1849  
# Line 3311 | Line 1857 | parse_aline(const char *cmd, struct Clie
1857      *up_p = user;
1858      *h_p = host;
1859    }
1860 <
1860 >
1861    parc--;
1862    parv++;
1863  
# Line 3324 | Line 1870 | parse_aline(const char *cmd, struct Clie
1870  
1871        if (target_server == NULL)
1872        {
1873 <        sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
1874 <                   me.name, source_p->name, cmd);
3329 <        return -1;
1873 >        sendto_one_notice(source_p, &me, ":ON server not supported by %s", cmd);
1874 >        return -1;
1875        }
1876  
1877        if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
1878        {
1879 <        sendto_one(source_p, form_str(ERR_NOPRIVS),
3335 <                   me.name, source_p->name, "remoteban");
1879 >        sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "remoteban");
1880          return -1;
1881        }
1882  
1883        if (parc == 0 || EmptyString(*parv))
1884        {
1885 <        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1886 <                   me.name, source_p->name, cmd);
3343 <        return -1;
1885 >        sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1886 >        return -1;
1887        }
1888  
1889        *target_server = *parv;
# Line 3353 | Line 1896 | parse_aline(const char *cmd, struct Clie
1896         * caller probably NULL'd it first, but no harm to do it again -db
1897         */
1898        if (target_server != NULL)
1899 <        *target_server = NULL;
1899 >        *target_server = NULL;
1900      }
1901    }
1902  
# Line 3361 | Line 1904 | parse_aline(const char *cmd, struct Clie
1904    {
1905      if (strchr(user, '!') != NULL)
1906      {
1907 <      sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3365 <                 me.name, source_p->name);
1907 >      sendto_one_notice(source_p, &me, ":Invalid character '!' in kline");
1908        return -1;
1909      }
1910  
# Line 3379 | Line 1921 | parse_aline(const char *cmd, struct Clie
1921      {
1922        *reason = *parv;
1923        if (!valid_comment(source_p, *reason, 1))
1924 <        return -1;
1924 >        return -1;
1925      }
1926      else
1927        *reason = def_reason;
# Line 3418 | Line 1960 | find_user_host(struct Client *source_p,
1960      {
1961        *(hostp++) = '\0';                       /* short and squat */
1962        if (*user_host_or_nick)
1963 <        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
1963 >        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
1964        else
1965 <        strcpy(luser, "*");
1965 >        strcpy(luser, "*");
1966 >
1967        if (*hostp)
1968 <        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
1968 >        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
1969        else
1970 <        strcpy(lhost, "*");
1970 >        strcpy(lhost, "*");
1971      }
1972      else
1973      {
1974        luser[0] = '*';             /* no @ found, assume its *@somehost */
1975 <      luser[1] = '\0';    
1975 >      luser[1] = '\0';
1976        strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
1977      }
1978 <    
1978 >
1979      return 1;
1980    }
1981 <  else if (!(flags & NOUSERLOOKUP))
1981 >  else
1982    {
1983      /* Try to find user@host mask from nick */
1984      /* Okay to use source_p as the first param, because source_p == client_p */
1985 <    if ((target_p =
1986 <        find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
1987 <      return 0;
1985 >    if ((target_p =
1986 >        find_chasing(source_p, user_host_or_nick)) == NULL)
1987 >      return 0;  /* find_chasing sends ERR_NOSUCHNICK */
1988  
1989      if (IsExemptKline(target_p))
1990      {
1991        if (!IsServer(source_p))
1992 <        sendto_one(source_p,
3450 <                   ":%s NOTICE %s :%s is E-lined",
3451 <                   me.name, source_p->name, target_p->name);
1992 >        sendto_one_notice(source_p, &me, ":%s is E-lined", target_p->name);
1993        return 0;
1994      }
1995  
# Line 3483 | Line 2024 | find_user_host(struct Client *source_p,
2024   int
2025   valid_comment(struct Client *source_p, char *comment, int warn)
2026   {
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
2027    if (strlen(comment) > REASONLEN)
2028      comment[REASONLEN-1] = '\0';
2029  
# Line 3505 | Line 2038 | valid_comment(struct Client *source_p, c
2038   * side effects - none
2039   */
2040   int
2041 < match_conf_password(const char *password, const struct AccessItem *aconf)
2041 > match_conf_password(const char *password, const struct MaskItem *conf)
2042   {
2043    const char *encr = NULL;
2044  
2045 <  if (password == NULL || aconf->passwd == NULL)
2045 >  if (EmptyString(password) || EmptyString(conf->passwd))
2046      return 0;
2047  
2048 <  if (aconf->flags & CONF_FLAGS_ENCRYPTED)
2049 <  {
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 <  }
2048 >  if (conf->flags & CONF_FLAGS_ENCRYPTED)
2049 >    encr = crypt(password, conf->passwd);
2050    else
2051      encr = password;
2052  
2053 <  return !strcmp(encr, aconf->passwd);
2053 >  return encr && !strcmp(encr, conf->passwd);
2054   }
2055  
2056   /*
# Line 3536 | Line 2058 | match_conf_password(const char *password
2058   *
2059   * inputs       - client sending the cluster
2060   *              - command name "KLINE" "XLINE" etc.
2061 < *              - capab -- CAP_KLN etc. from s_serv.h
2061 > *              - capab -- CAP_KLN etc. from server.h
2062   *              - cluster type -- CLUSTER_KLINE etc. from conf.h
2063   *              - pattern and args to send along
2064   * output       - none
# Line 3548 | Line 2070 | cluster_a_line(struct Client *source_p,
2070                 int capab, int cluster_type, const char *pattern, ...)
2071   {
2072    va_list args;
2073 <  char buffer[IRCD_BUFSIZE];
2073 >  char buffer[IRCD_BUFSIZE] = "";
2074    const dlink_node *ptr = NULL;
2075  
2076    va_start(args, pattern);
# Line 3557 | Line 2079 | cluster_a_line(struct Client *source_p,
2079  
2080    DLINK_FOREACH(ptr, cluster_items.head)
2081    {
2082 <    const struct ConfItem *conf = ptr->data;
2082 >    const struct MaskItem *conf = ptr->data;
2083  
2084      if (conf->flags & cluster_type)
2085        sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
2086 <                         "%s %s %s", command, conf->name, buffer);
2086 >                         "%s %s %s", command, conf->name, buffer);
2087    }
2088   }
2089  
# Line 3609 | Line 2131 | split_nuh(struct split_nuh_item *const i
2131    {
2132      *p = '\0';
2133  
2134 <    if (iptr->nickptr && *iptr->nuhmask != '\0')
2134 >    if (iptr->nickptr && *iptr->nuhmask)
2135        strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
2136  
2137 <    if ((q = strchr(++p, '@'))) {
2137 >    if ((q = strchr(++p, '@')))
2138 >    {
2139        *q++ = '\0';
2140  
2141 <      if (*p != '\0')
2141 >      if (*p)
2142          strlcpy(iptr->userptr, p, iptr->usersize);
2143  
2144 <      if (*q != '\0')
2144 >      if (*q)
2145          strlcpy(iptr->hostptr, q, iptr->hostsize);
2146      }
2147      else
2148      {
2149 <      if (*p != '\0')
2149 >      if (*p)
2150          strlcpy(iptr->userptr, p, iptr->usersize);
2151      }
2152    }
# Line 3635 | Line 2158 | split_nuh(struct split_nuh_item *const i
2158        /* if found a @ */
2159        *p++ = '\0';
2160  
2161 <      if (*iptr->nuhmask != '\0')
2161 >      if (*iptr->nuhmask)
2162          strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
2163  
2164 <      if (*p != '\0')
2164 >      if (*p)
2165          strlcpy(iptr->hostptr, p, iptr->hostsize);
2166      }
2167      else
# Line 3651 | Line 2174 | split_nuh(struct split_nuh_item *const i
2174      }
2175    }
2176   }
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)