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

Comparing:
ircd-hybrid-8/src/s_conf.c (file contents), Revision 1176 by michael, Sun Aug 14 11:24:24 2011 UTC vs.
ircd-hybrid/trunk/src/conf.c (file contents), Revision 4019 by michael, Fri Jun 20 16:06:42 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  s_conf.c: Configuration file functions.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 18 | Line 17
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file conf.c
23 > * \brief Configuration file functions.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28   #include "list.h"
29   #include "ircd_defs.h"
30 < #include "balloc.h"
31 < #include "s_conf.h"
30 < #include "s_serv.h"
30 > #include "conf.h"
31 > #include "server.h"
32   #include "resv.h"
33   #include "channel.h"
34   #include "client.h"
34 #include "common.h"
35   #include "event.h"
36 #include "hash.h"
37 #include "hook.h"
36   #include "irc_string.h"
39 #include "sprintf_irc.h"
37   #include "s_bsd.h"
38   #include "ircd.h"
39   #include "listener.h"
# Line 44 | Line 41
41   #include "modules.h"
42   #include "numeric.h"
43   #include "fdlist.h"
44 < #include "s_log.h"
44 > #include "log.h"
45   #include "send.h"
49 #include "s_gline.h"
50 #include "fileio.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 "misc.h"
54 + #include "conf_db.h"
55 + #include "conf_class.h"
56 + #include "motd.h"
57 +
58  
59 < struct Callback *client_check_cb = NULL;
59 > struct config_channel_entry ConfigChannel;
60   struct config_server_hide ConfigServerHide;
61 + struct config_file_entry ConfigFileEntry;
62 + struct logging_entry ConfigLoggingEntry = { .use_logging = 1 };
63 + struct server_info ServerInfo;
64 + struct admin_info AdminInfo;
65  
66   /* general conf items link list root, other than k lines etc. */
67   dlink_list service_items = { NULL, NULL, 0 };
68   dlink_list server_items  = { NULL, NULL, 0 };
69   dlink_list cluster_items = { NULL, NULL, 0 };
64 dlink_list hub_items     = { NULL, NULL, 0 };
65 dlink_list leaf_items    = { NULL, NULL, 0 };
70   dlink_list oconf_items   = { NULL, NULL, 0 };
71   dlink_list uconf_items   = { NULL, NULL, 0 };
72   dlink_list xconf_items   = { NULL, NULL, 0 };
69 dlink_list rxconf_items  = { NULL, NULL, 0 };
70 dlink_list rkconf_items  = { NULL, NULL, 0 };
73   dlink_list nresv_items   = { NULL, NULL, 0 };
74 < 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 };
74 > dlink_list cresv_items = { NULL, NULL, 0 };
75  
76   extern unsigned int lineno;
77   extern char linebuf[];
78   extern char conffilebuf[IRCD_BUFSIZE];
86 extern char yytext[];
79   extern int yyparse(); /* defined in y.tab.c */
80  
81   struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
82  
83   /* internally defined functions */
84 < static void lookup_confhost(struct ConfItem *);
93 < static void set_default_conf(void);
94 < static void validate_conf(void);
95 < static void read_conf(FBFILE *);
84 > static void read_conf(FILE *);
85   static void clear_out_old_conf(void);
97 static void flush_deleted_I_P(void);
86   static void expire_tklines(dlink_list *);
87   static void garbage_collect_ip_entries(void);
88   static int hash_ip(struct irc_ssaddr *);
89 < static int verify_access(struct Client *, const char *);
90 < static int attach_iline(struct Client *, struct ConfItem *);
89 > static int verify_access(struct Client *);
90 > static int attach_iline(struct Client *, struct MaskItem *);
91   static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
92 < static void parse_conf_file(int, int);
105 < static dlink_list *map_to_list(ConfType);
106 < static struct AccessItem *find_regexp_kline(const char *[]);
92 > static dlink_list *map_to_list(enum maskitem_type);
93   static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
94  
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;
95  
96   /* usually, with hash tables, you use a prime number...
97   * but in this case I am dealing with ip addresses,
# Line 127 | Line 102 | static struct ConfItem *class_default;
102   struct ip_entry
103   {
104    struct irc_ssaddr ip;
105 <  int count;
106 <  time_t last_attempt;
105 >  unsigned int count;  /**< Number of registered users using this IP */
106 >  unsigned int connection_count;  /**< Number of connections from this IP in the last throttle_time duration */
107 >  time_t last_attempt;  /**< The last time someone connected from this IP */
108    struct ip_entry *next;
109   };
110  
111   static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
112 < static BlockHeap *ip_entry_heap = NULL;
112 > static mp_pool_t *ip_entry_pool = NULL;
113   static int ip_entries_count = 0;
114  
115  
140 void *
141 map_to_conf(struct ConfItem *aconf)
142 {
143  void *conf;
144  conf = (void *)((uintptr_t)aconf +
145                  (uintptr_t)sizeof(struct ConfItem));
146  return(conf);
147 }
148
149 struct ConfItem *
150 unmap_conf_item(void *aconf)
151 {
152  struct ConfItem *conf;
153
154  conf = (struct ConfItem *)((uintptr_t)aconf -
155                             (uintptr_t)sizeof(struct ConfItem));
156  return(conf);
157 }
158
116   /* conf_dns_callback()
117   *
118 < * inputs       - pointer to struct AccessItem
118 > * inputs       - pointer to struct MaskItem
119   *              - pointer to DNSReply reply
120   * output       - none
121   * side effects - called when resolver query finishes
# Line 169 | Line 126 | unmap_conf_item(void *aconf)
126   static void
127   conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
128   {
129 <  struct AccessItem *aconf = vptr;
129 >  struct MaskItem *conf = vptr;
130  
131 <  aconf->dns_pending = 0;
131 >  conf->dns_pending = 0;
132  
133 <  if (addr != NULL)
134 <    memcpy(&aconf->ipnum, addr, sizeof(aconf->ipnum));
133 >  if (addr)
134 >    memcpy(&conf->addr, addr, sizeof(conf->addr));
135    else
136 <    aconf->dns_failed = 1;
136 >    conf->dns_failed = 1;
137   }
138  
139   /* conf_dns_lookup()
# Line 186 | Line 143 | conf_dns_callback(void *vptr, const stru
143   * allocate a dns_query and start ns lookup.
144   */
145   static void
146 < conf_dns_lookup(struct AccessItem *aconf)
146 > conf_dns_lookup(struct MaskItem *conf)
147   {
148 <  if (!aconf->dns_pending)
148 >  if (!conf->dns_pending)
149    {
150 <    aconf->dns_pending = 1;
151 <    gethost_byname(conf_dns_callback, aconf, aconf->host);
150 >    conf->dns_pending = 1;
151 >    gethost_byname(conf_dns_callback, conf, conf->host);
152    }
153   }
154  
155 < /* make_conf_item()
156 < *
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)
155 > struct MaskItem *
156 > conf_make(enum maskitem_type type)
157   {
158 <  struct ConfItem *conf = NULL;
159 <  struct AccessItem *aconf = NULL;
209 <  struct ClassItem *aclass = NULL;
210 <  int status = 0;
211 <
212 <  switch (type)
213 <  {
214 <  case DLINE_TYPE:
215 <  case EXEMPTDLINE_TYPE:
216 <  case GLINE_TYPE:
217 <  case KLINE_TYPE:
218 <  case CLIENT_TYPE:
219 <  case OPER_TYPE:
220 <  case SERVER_TYPE:
221 <    conf = MyMalloc(sizeof(struct ConfItem) +
222 <                    sizeof(struct AccessItem));
223 <    aconf = map_to_conf(conf);
224 <    aconf->aftype = AF_INET;
225 <
226 <    /* Yes, sigh. switch on type again */
227 <    switch (type)
228 <    {
229 <    case EXEMPTDLINE_TYPE:
230 <      status = CONF_EXEMPTDLINE;
231 <      break;
232 <
233 <    case DLINE_TYPE:
234 <      status = CONF_DLINE;
235 <      break;
158 >  struct MaskItem *conf = MyCalloc(sizeof(*conf));
159 >  dlink_list *list = NULL;
160  
161 <    case KLINE_TYPE:
162 <      status = CONF_KLINE;
163 <      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;
161 >  conf->type   = type;
162 >  conf->active = 1;
163 >  conf->aftype = AF_INET;
164  
165 +  if ((list = map_to_list(type)))
166 +    dlinkAdd(conf, &conf->node, list);
167    return conf;
168   }
169  
170   void
171 < delete_conf_item(struct ConfItem *conf)
171 > conf_free(struct MaskItem *conf)
172   {
173 <  dlink_node *m = NULL;
174 <  struct MatchItem *match_item;
175 <  struct AccessItem *aconf;
176 <  ConfType type = conf->type;
173 >  dlink_node *ptr = NULL, *ptr_next = NULL;
174 >  dlink_list *list = NULL;
175 >
176 >  if (conf->node.next)
177 >    if ((list = map_to_list(conf->type)))
178 >      dlinkDelete(&conf->node, list);
179  
180    MyFree(conf->name);
365  conf->name = NULL;
181  
182 <  switch(type)
183 <  {
184 <  case DLINE_TYPE:
185 <  case EXEMPTDLINE_TYPE:
186 <  case GLINE_TYPE:
187 <  case KLINE_TYPE:
188 <  case CLIENT_TYPE:
189 <  case OPER_TYPE:
190 <  case SERVER_TYPE:
191 <    aconf = map_to_conf(conf);
192 <
193 <    if (aconf->dns_pending)
194 <      delete_resolver_queries(aconf);
195 <    if (aconf->passwd != NULL)
196 <      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);
182 >  if (conf->dns_pending)
183 >    delete_resolver_queries(conf);
184 >  if (conf->passwd)
185 >    memset(conf->passwd, 0, strlen(conf->passwd));
186 >  if (conf->spasswd)
187 >    memset(conf->spasswd, 0, strlen(conf->spasswd));
188 >
189 >  conf->class = NULL;
190 >
191 >  MyFree(conf->passwd);
192 >  MyFree(conf->spasswd);
193 >  MyFree(conf->reason);
194 >  MyFree(conf->certfp);
195 >  MyFree(conf->user);
196 >  MyFree(conf->host);
197   #ifdef HAVE_LIBCRYPTO
198 <    if (aconf->rsa_public_key)
394 <      RSA_free(aconf->rsa_public_key);
395 <    MyFree(aconf->rsa_public_key_file);
396 < #endif
198 >  MyFree(conf->cipher_list);
199  
200 <    /* Yes, sigh. switch on type again */
201 <    switch(type)
400 <    {
401 <    case EXEMPTDLINE_TYPE:
402 <    case DLINE_TYPE:
403 <    case GLINE_TYPE:
404 <    case KLINE_TYPE:
405 <    case CLIENT_TYPE:
406 <      MyFree(conf);
407 <      break;
408 <
409 <    case OPER_TYPE:
410 <      aconf = map_to_conf(conf);
411 <      if (!IsConfIllegal(aconf))
412 <        dlinkDelete(&conf->node, &oconf_items);
413 <      MyFree(conf);
414 <      break;
415 <
416 <    case SERVER_TYPE:
417 <      aconf = map_to_conf(conf);
418 <      if (!IsConfIllegal(aconf))
419 <        dlinkDelete(&conf->node, &server_items);
420 <      MyFree(conf);
421 <      break;
422 <
423 <    default:
424 <      break;
425 <    }
426 <    break;
427 <
428 <  case HUB_TYPE:
429 <    match_item = map_to_conf(conf);
430 <    MyFree(match_item->user);
431 <    MyFree(match_item->host);
432 <    MyFree(match_item->reason);
433 <    MyFree(match_item->oper_reason);
434 <    /* If marked illegal, its already been pulled off of the hub_items list */
435 <    if (!match_item->illegal)
436 <      dlinkDelete(&conf->node, &hub_items);
437 <    MyFree(conf);
438 <    break;
439 <
440 <  case LEAF_TYPE:
441 <    match_item = map_to_conf(conf);
442 <    MyFree(match_item->user);
443 <    MyFree(match_item->host);
444 <    MyFree(match_item->reason);
445 <    MyFree(match_item->oper_reason);
446 <    /* If marked illegal, its already been pulled off of the leaf_items list */
447 <    if (!match_item->illegal)
448 <      dlinkDelete(&conf->node, &leaf_items);
449 <    MyFree(conf);
450 <    break;
451 <
452 <  case ULINE_TYPE:
453 <    match_item = map_to_conf(conf);
454 <    MyFree(match_item->user);
455 <    MyFree(match_item->host);
456 <    MyFree(match_item->reason);
457 <    MyFree(match_item->oper_reason);
458 <    dlinkDelete(&conf->node, &uconf_items);
459 <    MyFree(conf);
460 <    break;
461 <
462 <  case XLINE_TYPE:
463 <    match_item = map_to_conf(conf);
464 <    MyFree(match_item->user);
465 <    MyFree(match_item->host);
466 <    MyFree(match_item->reason);
467 <    MyFree(match_item->oper_reason);
468 <    dlinkDelete(&conf->node, &xconf_items);
469 <    MyFree(conf);
470 <    break;
471 < #ifdef HAVE_LIBPCRE
472 <  case RKLINE_TYPE:
473 <    aconf = map_to_conf(conf);
474 <    MyFree(aconf->regexuser);
475 <    MyFree(aconf->regexhost);
476 <    MyFree(aconf->user);
477 <    MyFree(aconf->host);
478 <    MyFree(aconf->reason);
479 <    MyFree(aconf->oper_reason);
480 <    dlinkDelete(&conf->node, &rkconf_items);
481 <    MyFree(conf);
482 <    break;
483 <
484 <  case RXLINE_TYPE:
485 <    MyFree(conf->regexpname);
486 <    match_item = map_to_conf(conf);
487 <    MyFree(match_item->user);
488 <    MyFree(match_item->host);
489 <    MyFree(match_item->reason);
490 <    MyFree(match_item->oper_reason);
491 <    dlinkDelete(&conf->node, &rxconf_items);
492 <    MyFree(conf);
493 <    break;
200 >  if (conf->rsa_public_key)
201 >    RSA_free(conf->rsa_public_key);
202   #endif
203 <  case NRESV_TYPE:
204 <    match_item = map_to_conf(conf);
205 <    MyFree(match_item->user);
206 <    MyFree(match_item->host);
207 <    MyFree(match_item->reason);
500 <    MyFree(match_item->oper_reason);
501 <    dlinkDelete(&conf->node, &nresv_items);
502 <
503 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
504 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
505 <        free_dlink_node(m);
506 <
507 <    MyFree(conf);
508 <    break;
509 <
510 <  case GDENY_TYPE:
511 <    aconf = map_to_conf(conf);
512 <    MyFree(aconf->user);
513 <    MyFree(aconf->host);
514 <    dlinkDelete(&conf->node, &gdeny_items);
515 <    MyFree(conf);
516 <    break;
517 <
518 <  case CLUSTER_TYPE:
519 <    dlinkDelete(&conf->node, &cluster_items);
520 <    MyFree(conf);
521 <    break;
522 <
523 <  case CRESV_TYPE:
524 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
525 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
526 <        free_dlink_node(m);
527 <
528 <    MyFree(conf);
529 <    break;
530 <
531 <  case CLASS_TYPE:
532 <    dlinkDelete(&conf->node, &class_items);
533 <    MyFree(conf);
534 <    break;
535 <
536 <  case SERVICE_TYPE:
537 <    dlinkDelete(&conf->node, &service_items);
538 <    MyFree(conf);
539 <    break;
540 <
541 <  default:
542 <    break;
203 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->hub_list.head)
204 >  {
205 >    MyFree(ptr->data);
206 >    dlinkDelete(ptr, &conf->hub_list);
207 >    free_dlink_node(ptr);
208    }
544 }
545
546 /* free_access_item()
547 *
548 * inputs       - pointer to conf to free
549 * output       - none
550 * side effects - crucial password fields are zeroed, conf is freed
551 */
552 void
553 free_access_item(struct AccessItem *aconf)
554 {
555  struct ConfItem *conf;
209  
210 <  if (aconf == NULL)
558 <    return;
559 <  conf = unmap_conf_item(aconf);
560 <  delete_conf_item(conf);
561 < }
562 <
563 < static const unsigned int shared_bit_table[] =
564 <  { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
565 <
566 < /* report_confitem_types()
567 < *
568 < * inputs       - pointer to client requesting confitem report
569 < *              - ConfType to report
570 < * output       - none
571 < * side effects -
572 < */
573 < void
574 < report_confitem_types(struct Client *source_p, ConfType type, int temp)
575 < {
576 <  dlink_node *ptr = NULL;
577 <  struct ConfItem *conf = NULL;
578 <  struct AccessItem *aconf = NULL;
579 <  struct MatchItem *matchitem = NULL;
580 <  struct ClassItem *classitem = NULL;
581 <  char buf[12];
582 <  char *p = NULL;
583 <  const char *pfx = NULL;
584 <
585 <  switch (type)
210 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->leaf_list.head)
211    {
212 <  case GDENY_TYPE:
213 <    DLINK_FOREACH(ptr, gdeny_items.head)
214 <    {
215 <      conf = ptr->data;
591 <      aconf = map_to_conf(conf);
592 <
593 <      p = buf;
594 <
595 <      if (aconf->flags & GDENY_BLOCK)
596 <        *p++ = 'B';
597 <      else
598 <        *p++ = 'b';
599 <
600 <      if (aconf->flags & GDENY_REJECT)
601 <        *p++ = 'R';
602 <      else
603 <        *p++ = 'r';
604 <
605 <      *p = '\0';
606 <
607 <      sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
608 <                 me.name, RPL_STATSDEBUG, source_p->name,
609 <                 aconf->user, aconf->host, conf->name, buf);
610 <    }
611 <    break;
612 <
613 <  case XLINE_TYPE:
614 <    DLINK_FOREACH(ptr, xconf_items.head)
615 <    {
616 <      conf = ptr->data;
617 <      matchitem = map_to_conf(conf);
618 <
619 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
620 <                 me.name, source_p->name,
621 <                 matchitem->hold ? "x": "X", matchitem->count,
622 <                 conf->name, matchitem->reason);
623 <    }
624 <    break;
625 <
626 < #ifdef HAVE_LIBPCRE
627 <  case RXLINE_TYPE:
628 <    DLINK_FOREACH(ptr, rxconf_items.head)
629 <    {
630 <      conf = ptr->data;
631 <      matchitem = map_to_conf(conf);
632 <
633 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
634 <                 me.name, source_p->name,
635 <                 matchitem->hold ? "xR": "XR", matchitem->count,
636 <                 conf->name, matchitem->reason);
637 <    }
638 <    break;
639 <
640 <  case RKLINE_TYPE:
641 <    pfx = temp ? "kR" : "KR";
642 <
643 <    DLINK_FOREACH(ptr, rkconf_items.head)
644 <    {
645 <      aconf = map_to_conf((conf = ptr->data));
646 <
647 <      if (temp && !(conf->flags & CONF_FLAGS_TEMPORARY))
648 <        continue;
649 <
650 <      sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
651 <                 source_p->name, pfx, aconf->host, aconf->user,
652 <                 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
653 <    }
654 <    break;
655 < #endif
656 <
657 <  case ULINE_TYPE:
658 <    DLINK_FOREACH(ptr, uconf_items.head)
659 <    {
660 <      conf = ptr->data;
661 <      matchitem = map_to_conf(conf);
662 <
663 <      p = buf;
664 <
665 <      /* some of these are redundant for the sake of
666 <       * consistency with cluster{} flags
667 <       */
668 <      *p++ = 'c';
669 <      flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
670 <
671 <      sendto_one(source_p, form_str(RPL_STATSULINE),
672 <                 me.name, source_p->name, conf->name,
673 <                 matchitem->user?matchitem->user: "*",
674 <                 matchitem->host?matchitem->host: "*", buf);
675 <    }
676 <
677 <    DLINK_FOREACH(ptr, cluster_items.head)
678 <    {
679 <      conf = ptr->data;
680 <
681 <      p = buf;
682 <
683 <      *p++ = 'C';
684 <      flags_to_ascii(conf->flags, shared_bit_table, p, 0);
685 <
686 <      sendto_one(source_p, form_str(RPL_STATSULINE),
687 <                 me.name, source_p->name, conf->name,
688 <                 "*", "*", buf);
689 <    }
690 <
691 <    break;
692 <
693 <  case OPER_TYPE:
694 <    DLINK_FOREACH(ptr, oconf_items.head)
695 <    {
696 <      conf = ptr->data;
697 <      aconf = map_to_conf(conf);
698 <
699 <      /* Don't allow non opers to see oper privs */
700 <      if (IsOper(source_p))
701 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
702 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
703 <                   conf->name, oper_privs_as_string(aconf->port),
704 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
705 <      else
706 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
707 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
708 <                   conf->name, "0",
709 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
710 <    }
711 <    break;
712 <
713 <  case CLASS_TYPE:
714 <    DLINK_FOREACH(ptr, class_items.head)
715 <    {
716 <      conf = ptr->data;
717 <      classitem = map_to_conf(conf);
718 <      sendto_one(source_p, form_str(RPL_STATSYLINE),
719 <                 me.name, source_p->name, 'Y',
720 <                 conf->name, PingFreq(classitem),
721 <                 ConFreq(classitem),
722 <                 MaxTotal(classitem), MaxSendq(classitem),
723 <                 CurrUserCount(classitem),
724 <                 classitem->active ? "active" : "disabled");
725 <    }
726 <    break;
727 <
728 <  case CONF_TYPE:
729 <  case CLIENT_TYPE:
730 <    break;
731 <
732 <  case SERVICE_TYPE:
733 <    DLINK_FOREACH(ptr, service_items.head)
734 <    {
735 <      conf = ptr->data;
736 <      sendto_one(source_p, form_str(RPL_STATSSERVICE),
737 <                 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
738 <    }
739 <    break;
740 <
741 <  case SERVER_TYPE:
742 <    DLINK_FOREACH(ptr, server_items.head)
743 <    {
744 <      p = buf;
745 <
746 <      conf = ptr->data;
747 <      aconf = map_to_conf(conf);
748 <
749 <      buf[0] = '\0';
750 <
751 <      if (IsConfAllowAutoConn(aconf))
752 <        *p++ = 'A';
753 <      if (IsConfCryptLink(aconf))
754 <        *p++ = 'C';
755 <      if (IsConfTopicBurst(aconf))
756 <        *p++ = 'T';
757 <      if (IsConfCompressed(aconf))
758 <        *p++ = 'Z';
759 <      if (buf[0] == '\0')
760 <        *p++ = '*';
761 <
762 <      *p = '\0';
763 <
764 <      /*
765 <       * Allow admins to see actual ips unless hide_server_ips is enabled
766 <       */
767 <      if (!ConfigServerHide.hide_server_ips && IsAdmin(source_p))
768 <        sendto_one(source_p, form_str(RPL_STATSCLINE),
769 <                   me.name, source_p->name, 'C', aconf->host,
770 <                   buf, conf->name, aconf->port,
771 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
772 <        else
773 <          sendto_one(source_p, form_str(RPL_STATSCLINE),
774 <                     me.name, source_p->name, 'C',
775 <                     "*@127.0.0.1", buf, conf->name, aconf->port,
776 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
777 <    }
778 <    break;
779 <
780 <  case HUB_TYPE:
781 <    DLINK_FOREACH(ptr, hub_items.head)
782 <    {
783 <      conf = ptr->data;
784 <      matchitem = map_to_conf(conf);
785 <      sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
786 <                 source_p->name, 'H', matchitem->host, conf->name, 0, "*");
787 <    }
788 <    break;
212 >    MyFree(ptr->data);
213 >    dlinkDelete(ptr, &conf->leaf_list);
214 >    free_dlink_node(ptr);
215 >  }
216  
217 <  case LEAF_TYPE:
218 <    DLINK_FOREACH(ptr, leaf_items.head)
219 <    {
793 <      conf = ptr->data;
794 <      matchitem = map_to_conf(conf);
795 <      sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
796 <                 source_p->name, 'L', matchitem->host, conf->name, 0, "*");
797 <    }
798 <    break;
217 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->exempt_list.head)
218 >  {
219 >    struct exempt *exptr = ptr->data;
220  
221 <  case GLINE_TYPE:
222 <  case KLINE_TYPE:
223 <  case DLINE_TYPE:
224 <  case EXEMPTDLINE_TYPE:
225 <  case CRESV_TYPE:
805 <  case NRESV_TYPE:
806 <  case CLUSTER_TYPE:
807 <  default:
808 <    break;
221 >    dlinkDelete(ptr, &conf->exempt_list);
222 >    MyFree(exptr->name);
223 >    MyFree(exptr->user);
224 >    MyFree(exptr->host);
225 >    MyFree(exptr);
226    }
227 +
228 +  MyFree(conf);
229   }
230  
231   /* check_client()
# Line 822 | Line 241 | report_confitem_types(struct Client *sou
241   *                Look for conf lines which have the same
242   *                status as the flags passed.
243   */
244 < static void *
245 < check_client(va_list args)
244 > int
245 > check_client(struct Client *source_p)
246   {
828  struct Client *source_p = va_arg(args, struct Client *);
829  const char *username = va_arg(args, const char *);
247    int i;
248 <
249 <  /* I'm already in big trouble if source_p->localClient is NULL -db */
250 <  if ((i = verify_access(source_p, username)))
834 <    ilog(L_INFO, "Access denied: %s[%s]",
248 >
249 >  if ((i = verify_access(source_p)))
250 >    ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
251           source_p->name, source_p->sockhost);
252  
253    switch (i)
254    {
255      case TOO_MANY:
256 <      sendto_realops_flags(UMODE_FULL, L_ALL,
256 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
257                             "Too many on IP for %s (%s).",
258 <                           get_client_name(source_p, SHOW_IP),
259 <                           source_p->sockhost);
260 <      ilog(L_INFO,"Too many connections on IP from %s.",
261 <           get_client_name(source_p, SHOW_IP));
258 >                           get_client_name(source_p, SHOW_IP),
259 >                           source_p->sockhost);
260 >      ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
261 >           get_client_name(source_p, SHOW_IP));
262        ++ServerStats.is_ref;
263 <      exit_client(source_p, &me, "No more connections allowed on that IP");
263 >      exit_client(source_p, "No more connections allowed on that IP");
264        break;
265  
266      case I_LINE_FULL:
267 <      sendto_realops_flags(UMODE_FULL, L_ALL,
268 <                           "I-line is full for %s (%s).",
269 <                           get_client_name(source_p, SHOW_IP),
270 <                           source_p->sockhost);
271 <      ilog(L_INFO,"Too many connections from %s.",
272 <           get_client_name(source_p, SHOW_IP));
267 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
268 >                           "auth{} block is full for %s (%s).",
269 >                           get_client_name(source_p, SHOW_IP),
270 >                           source_p->sockhost);
271 >      ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
272 >           get_client_name(source_p, SHOW_IP));
273        ++ServerStats.is_ref;
274 <      exit_client(source_p, &me,
859 <                "No more connections allowed in your connection class");
274 >      exit_client(source_p, "No more connections allowed in your connection class");
275        break;
276  
277      case NOT_AUTHORIZED:
278        ++ServerStats.is_ref;
279        /* jdc - lists server name & port connections are on */
280        /*       a purely cosmetical change */
281 <      sendto_realops_flags(UMODE_UNAUTH, L_ALL,
282 <                           "Unauthorized client connection from %s [%s] on [%s/%u].",
283 <                           get_client_name(source_p, SHOW_IP),
284 <                           source_p->sockhost,
285 <                           source_p->localClient->listener->name,
286 <                           source_p->localClient->listener->port);
287 <      ilog(L_INFO,
288 <          "Unauthorized client connection from %s on [%s/%u].",
289 <          get_client_name(source_p, SHOW_IP),
290 <          source_p->localClient->listener->name,
291 <          source_p->localClient->listener->port);
292 <
293 <      /* XXX It is prolematical whether it is better to use the
879 <       * capture reject code here or rely on the connecting too fast code.
880 <       * - Dianora
881 <       */
882 <      if (REJECT_HOLD_TIME > 0)
883 <      {
884 <        sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
885 <                   me.name, source_p->name);
886 <        source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
887 <        SetCaptured(source_p);
888 <      }
889 <      else
890 <        exit_client(source_p, &me, "You are not authorized to use this server");
281 >      sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
282 >                           "Unauthorized client connection from %s [%s] on [%s/%u].",
283 >                           get_client_name(source_p, SHOW_IP),
284 >                           source_p->sockhost,
285 >                           source_p->localClient->listener->name,
286 >                           source_p->localClient->listener->port);
287 >      ilog(LOG_TYPE_IRCD,
288 >           "Unauthorized client connection from %s on [%s/%u].",
289 >           get_client_name(source_p, SHOW_IP),
290 >           source_p->localClient->listener->name,
291 >           source_p->localClient->listener->port);
292 >
293 >      exit_client(source_p, "You are not authorized to use this server");
294        break;
295  
296     case BANNED_CLIENT:
297 <     /*
895 <      * Don't exit them immediately, play with them a bit.
896 <      * - Dianora
897 <      */
898 <     if (REJECT_HOLD_TIME > 0)
899 <     {
900 <       source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
901 <       SetCaptured(source_p);
902 <     }
903 <     else
904 <       exit_client(source_p, &me, "Banned");
297 >     exit_client(source_p, "Banned");
298       ++ServerStats.is_ref;
299       break;
300  
# Line 910 | Line 303 | check_client(va_list args)
303       break;
304    }
305  
306 <  return (i < 0 ? NULL : source_p);
306 >  return (i < 0 ? 0 : 1);
307   }
308  
309   /* verify_access()
310   *
311   * inputs       - pointer to client to verify
919 *              - pointer to proposed username
312   * output       - 0 if success -'ve if not
313   * side effect  - find the first (best) I line to attach.
314   */
315   static int
316 < verify_access(struct Client *client_p, const char *username)
316 > verify_access(struct Client *client_p)
317   {
318 <  struct AccessItem *aconf = NULL, *rkconf = NULL;
319 <  struct ConfItem *conf = NULL;
928 <  char non_ident[USERLEN + 1] = { '~', '\0' };
929 <  const char *uhi[3];
318 >  struct MaskItem *conf = NULL;
319 >  char non_ident[USERLEN + 1] = "~";
320  
321    if (IsGotId(client_p))
322    {
323 <    aconf = find_address_conf(client_p->host, client_p->username,
324 <                             &client_p->localClient->ip,
325 <                             client_p->localClient->aftype,
323 >    conf = find_address_conf(client_p->host, client_p->username,
324 >                             &client_p->localClient->ip,
325 >                             client_p->localClient->aftype,
326                               client_p->localClient->passwd);
327    }
328    else
329    {
330 <    strlcpy(non_ident+1, username, sizeof(non_ident)-1);
331 <    aconf = find_address_conf(client_p->host,non_ident,
332 <                             &client_p->localClient->ip,
333 <                             client_p->localClient->aftype,
334 <                             client_p->localClient->passwd);
330 >    strlcpy(non_ident + 1, client_p->username, sizeof(non_ident) - 1);
331 >    conf = find_address_conf(client_p->host,non_ident,
332 >                             &client_p->localClient->ip,
333 >                             client_p->localClient->aftype,
334 >                             client_p->localClient->passwd);
335    }
336  
337 <  uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
948 <  uhi[1] = client_p->host;
949 <  uhi[2] = client_p->sockhost;
950 <
951 <  rkconf = find_regexp_kline(uhi);
952 <
953 <  if (aconf != NULL)
337 >  if (conf)
338    {
339 <    if (IsConfClient(aconf) && !rkconf)
339 >    if (IsConfClient(conf))
340      {
341 <      conf = unmap_conf_item(aconf);
958 <
959 <      if (IsConfRedir(aconf))
341 >      if (IsConfRedir(conf))
342        {
343 <        sendto_one(client_p, form_str(RPL_REDIR),
344 <                   me.name, client_p->name,
345 <                   conf->name ? conf->name : "",
346 <                   aconf->port);
965 <        return(NOT_AUTHORIZED);
343 >        sendto_one_numeric(client_p, &me, RPL_REDIR,
344 >                           conf->name ? conf->name : "",
345 >                           conf->port);
346 >        return NOT_AUTHORIZED;
347        }
348  
349 <      if (IsConfDoIdentd(aconf))
350 <        SetNeedId(client_p);
349 >      if (IsConfDoIdentd(conf))
350 >        SetNeedId(client_p);
351  
352        /* Thanks for spoof idea amm */
353 <      if (IsConfDoSpoofIp(aconf))
353 >      if (IsConfDoSpoofIp(conf))
354        {
355 <        conf = unmap_conf_item(aconf);
356 <
357 <        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
977 <          sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
355 >        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(conf))
356 >          sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
357 >                               "%s spoofing: %s as %s",
358                                 client_p->name, client_p->host, conf->name);
359          strlcpy(client_p->host, conf->name, sizeof(client_p->host));
360 <        SetIPSpoof(client_p);
360 >        AddFlag(client_p, FLAGS_IP_SPOOFING | FLAGS_AUTH_SPOOF);
361        }
362  
363 <      return(attach_iline(client_p, conf));
363 >      return attach_iline(client_p, conf);
364      }
365 <    else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
365 >    else if (IsConfKill(conf) || (ConfigFileEntry.glines && IsConfGline(conf)))
366      {
367 <      /* XXX */
368 <      aconf = rkconf ? rkconf : aconf;
369 <      if (IsConfGline(aconf))
370 <        sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
991 <                   client_p->name);
992 <      if (ConfigFileEntry.kline_with_reason)
993 <        sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
994 <                  me.name, client_p->name, aconf->reason);
995 <      return(BANNED_CLIENT);
367 >      if (IsConfGline(conf))
368 >        sendto_one_notice(client_p, &me, ":*** G-lined");
369 >      sendto_one_notice(client_p, &me, ":*** Banned: %s", conf->reason);
370 >      return BANNED_CLIENT;
371      }
372    }
373  
374 <  return(NOT_AUTHORIZED);
374 >  return NOT_AUTHORIZED;
375   }
376  
377   /* attach_iline()
# Line 1007 | Line 382 | verify_access(struct Client *client_p, c
382   * side effects - do actual attach
383   */
384   static int
385 < attach_iline(struct Client *client_p, struct ConfItem *conf)
385 > attach_iline(struct Client *client_p, struct MaskItem *conf)
386   {
387 <  struct AccessItem *aconf;
1013 <  struct ClassItem *aclass;
387 >  struct ClassItem *class = NULL;
388    struct ip_entry *ip_found;
389    int a_limit_reached = 0;
390 <  int local = 0, global = 0, ident = 0;
390 >  unsigned int local = 0, global = 0, ident = 0;
391 >
392 >  assert(conf->class);
393  
394    ip_found = find_or_add_ip(&client_p->localClient->ip);
395    ip_found->count++;
396    SetIpHash(client_p);
397  
398 <  aconf = map_to_conf(conf);
1023 <  if (aconf->class_ptr == NULL)
1024 <    return NOT_AUTHORIZED;  /* If class is missing, this is best */
1025 <
1026 <  aclass = map_to_conf(aconf->class_ptr);
398 >  class = conf->class;
399  
400    count_user_host(client_p->username, client_p->host,
401                    &global, &local, &ident);
# Line 1032 | Line 404 | attach_iline(struct Client *client_p, st
404     * setting a_limit_reached if any limit is reached.
405     * - Dianora
406     */
407 <  if (MaxTotal(aclass) != 0 && CurrUserCount(aclass) >= MaxTotal(aclass))
407 >  if (class->max_total && class->ref_count >= class->max_total)
408      a_limit_reached = 1;
409 <  else if (MaxPerIp(aclass) != 0 && ip_found->count > MaxPerIp(aclass))
409 >  else if (class->max_perip && ip_found->count > class->max_perip)
410      a_limit_reached = 1;
411 <  else if (MaxLocal(aclass) != 0 && local >= MaxLocal(aclass))
411 >  else if (class->max_local && local >= class->max_local)
412      a_limit_reached = 1;
413 <  else if (MaxGlobal(aclass) != 0 && global >= MaxGlobal(aclass))
413 >  else if (class->max_global && global >= class->max_global)
414      a_limit_reached = 1;
415 <  else if (MaxIdent(aclass) != 0 && ident >= MaxIdent(aclass) &&
415 >  else if (class->max_ident && ident >= class->max_ident &&
416             client_p->username[0] != '~')
417      a_limit_reached = 1;
418  
419    if (a_limit_reached)
420    {
421 <    if (!IsConfExemptLimits(aconf))
421 >    if (!IsConfExemptLimits(conf))
422        return TOO_MANY;   /* Already at maximum allowed */
423  
424 <    sendto_one(client_p,
425 <               ":%s NOTICE %s :*** Your connection class is full, "
1054 <               "but you have exceed_limit = yes;", me.name, client_p->name);
424 >    sendto_one_notice(client_p, &me, ":*** Your connection class is full, "
425 >                      "but you have exceed_limit = yes;");
426    }
427  
428    return attach_conf(client_p, conf);
# Line 1067 | Line 438 | attach_iline(struct Client *client_p, st
438   void
439   init_ip_hash_table(void)
440   {
441 <  ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
1071 <    2 * hard_fdlimit);
441 >  ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
442    memset(ip_hash_table, 0, sizeof(ip_hash_table));
443   }
444  
# Line 1117 | Line 487 | find_or_add_ip(struct irc_ssaddr *ip_in)
487    if (ip_entries_count >= 2 * hard_fdlimit)
488      garbage_collect_ip_entries();
489  
490 <  newptr = BlockHeapAlloc(ip_entry_heap);
490 >  newptr = mp_pool_get(ip_entry_pool);
491 >  memset(newptr, 0, sizeof(*newptr));
492    ip_entries_count++;
493    memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
494  
# Line 1168 | Line 539 | remove_one_ip(struct irc_ssaddr *ip_in)
539      if (ptr->count > 0)
540        ptr->count--;
541      if (ptr->count == 0 &&
542 <        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
542 >        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
543      {
544        if (last_ptr != NULL)
545 <        last_ptr->next = ptr->next;
545 >        last_ptr->next = ptr->next;
546        else
547 <        ip_hash_table[hash_index] = ptr->next;
547 >        ip_hash_table[hash_index] = ptr->next;
548  
549 <      BlockHeapFree(ip_entry_heap, ptr);
549 >      mp_pool_release(ptr);
550        ip_entries_count--;
551        return;
552      }
# Line 1210 | Line 581 | hash_ip(struct irc_ssaddr *addr)
581      uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
582  
583      hash  = ip[0] ^ ip[3];
584 <    hash ^= hash >> 16;  
585 <    hash ^= hash >> 8;  
584 >    hash ^= hash >> 16;
585 >    hash ^= hash >> 8;
586      hash  = hash & (IP_HASH_SIZE - 1);
587      return hash;
588    }
# Line 1222 | Line 593 | hash_ip(struct irc_ssaddr *addr)
593  
594   /* count_ip_hash()
595   *
596 < * inputs        - pointer to counter of number of ips hashed
596 > * inputs        - pointer to counter of number of ips hashed
597   *               - pointer to memory used for ip hash
598   * output        - returned via pointers input
599   * side effects  - NONE
# Line 1234 | Line 605 | void
605   count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
606   {
607    struct ip_entry *ptr;
1237  int i;
608  
609    *number_ips_stored = 0;
610    *mem_ips_stored    = 0;
611  
612 <  for (i = 0; i < IP_HASH_SIZE; i++)
612 >  for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
613    {
614      for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
615      {
# Line 1261 | Line 631 | garbage_collect_ip_entries(void)
631    struct ip_entry *ptr;
632    struct ip_entry *last_ptr;
633    struct ip_entry *next_ptr;
1264  int i;
634  
635 <  for (i = 0; i < IP_HASH_SIZE; i++)
635 >  for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
636    {
637      last_ptr = NULL;
638  
# Line 1278 | Line 647 | garbage_collect_ip_entries(void)
647            last_ptr->next = ptr->next;
648          else
649            ip_hash_table[i] = ptr->next;
650 <        BlockHeapFree(ip_entry_heap, ptr);
650 >        mp_pool_release(ptr);
651          ip_entries_count--;
652        }
653        else
# Line 1295 | Line 664 | garbage_collect_ip_entries(void)
664   * side effects - Disassociate configuration from the client.
665   *                Also removes a class from the list if marked for deleting.
666   */
667 < int
668 < detach_conf(struct Client *client_p, ConfType type)
667 > void
668 > detach_conf(struct Client *client_p, enum maskitem_type type)
669   {
670 <  dlink_node *ptr, *next_ptr;
1302 <  struct ConfItem *conf;
1303 <  struct ClassItem *aclass;
1304 <  struct AccessItem *aconf;
1305 <  struct ConfItem *aclass_conf;
1306 <  struct MatchItem *match_item;
670 >  dlink_node *ptr = NULL, *ptr_next = NULL;
671  
672 <  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
672 >  DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->localClient->confs.head)
673    {
674 <    conf = ptr->data;
1311 <
1312 <    if (type == CONF_TYPE || conf->type == type)
1313 <    {
1314 <      dlinkDelete(ptr, &client_p->localClient->confs);
1315 <      free_dlink_node(ptr);
674 >    struct MaskItem *conf = ptr->data;
675  
676 <      switch (conf->type)
677 <      {
678 <      case CLIENT_TYPE:
1320 <      case OPER_TYPE:
1321 <      case SERVER_TYPE:
1322 <        aconf = map_to_conf(conf);
1323 <
1324 <        assert(aconf->clients > 0);
1325 <
1326 <        if ((aclass_conf = ClassPtr(aconf)) != NULL)
1327 <        {
1328 <          aclass = map_to_conf(aclass_conf);
1329 <
1330 <          assert(aclass->curr_user_count > 0);
1331 <
1332 <          if (conf->type == CLIENT_TYPE)
1333 <            remove_from_cidr_check(&client_p->localClient->ip, aclass);
1334 <          if (--aclass->curr_user_count == 0 && aclass->active == 0)
1335 <            delete_conf_item(aclass_conf);
1336 <        }
676 >    assert(conf->type & (CONF_CLIENT | CONF_OPER | CONF_SERVER));
677 >    assert(conf->ref_count > 0);
678 >    assert(conf->class->ref_count > 0);
679  
680 <        if (--aconf->clients == 0 && IsConfIllegal(aconf))
681 <          delete_conf_item(conf);
680 >    if (!(conf->type & type))
681 >      continue;
682  
683 <        break;
683 >    dlinkDelete(ptr, &client_p->localClient->confs);
684 >    free_dlink_node(ptr);
685  
686 <      case LEAF_TYPE:
687 <      case HUB_TYPE:
1345 <        match_item = map_to_conf(conf);
1346 <        if (match_item->ref_count == 0 && match_item->illegal)
1347 <          delete_conf_item(conf);
1348 <        break;
1349 <      default:
1350 <        break;
1351 <      }
686 >    if (conf->type == CONF_CLIENT)
687 >      remove_from_cidr_check(&client_p->localClient->ip, conf->class);
688  
689 <      if (type != CONF_TYPE)
690 <        return 0;
689 >    if (--conf->class->ref_count == 0 && conf->class->active == 0)
690 >    {
691 >      class_free(conf->class);
692 >      conf->class = NULL;
693      }
1356  }
694  
695 <  return -1;
695 >    if (--conf->ref_count == 0 && conf->active == 0)
696 >      conf_free(conf);
697 >  }
698   }
699  
700   /* attach_conf()
# Line 1369 | Line 708 | detach_conf(struct Client *client_p, Con
708   *                attachment if there was an old one...
709   */
710   int
711 < attach_conf(struct Client *client_p, struct ConfItem *conf)
711 > attach_conf(struct Client *client_p, struct MaskItem *conf)
712   {
713 <  if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
713 >  if (dlinkFind(&client_p->localClient->confs, conf))
714      return 1;
715  
716 <  if (conf->type == CLIENT_TYPE ||
717 <      conf->type == SERVER_TYPE ||
718 <      conf->type == OPER_TYPE)
719 <  {
1381 <    struct AccessItem *aconf = map_to_conf(conf);
1382 <    struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1383 <
1384 <    if (IsConfIllegal(aconf))
1385 <      return NOT_AUTHORIZED;
716 >  if (conf->type == CONF_CLIENT)
717 >    if (cidr_limit_reached(IsConfExemptLimits(conf),
718 >                           &client_p->localClient->ip, conf->class))
719 >      return TOO_MANY;    /* Already at maximum allowed */
720  
721 <    if (conf->type == CLIENT_TYPE)
722 <      if (cidr_limit_reached(IsConfExemptLimits(aconf),
1389 <                             &client_p->localClient->ip, aclass))
1390 <        return TOO_MANY;    /* Already at maximum allowed */
1391 <
1392 <    CurrUserCount(aclass)++;
1393 <    aconf->clients++;
1394 <  }
1395 <  else if (conf->type == HUB_TYPE || conf->type == LEAF_TYPE)
1396 <  {
1397 <    struct MatchItem *match_item = map_to_conf(conf);
1398 <    match_item->ref_count++;
1399 <  }
721 >  conf->class->ref_count++;
722 >  conf->ref_count++;
723  
724    dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
725  
# Line 1416 | Line 739 | attach_connect_block(struct Client *clie
739                       const char *host)
740   {
741    dlink_node *ptr;
742 <  struct ConfItem *conf;
1420 <  struct AccessItem *aconf;
742 >  struct MaskItem *conf = NULL;
743  
744    assert(client_p != NULL);
745    assert(host != NULL);
# Line 1428 | Line 750 | attach_connect_block(struct Client *clie
750    DLINK_FOREACH(ptr, server_items.head)
751    {
752      conf = ptr->data;
1431    aconf = map_to_conf(conf);
753  
754 <    if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
754 >    if (match(conf->name, name) || match(conf->host, host))
755        continue;
756  
757      attach_conf(client_p, conf);
# Line 1440 | Line 761 | attach_connect_block(struct Client *clie
761    return 0;
762   }
763  
1443 /* find_conf_exact()
1444 *
1445 * inputs       - type of ConfItem
1446 *              - pointer to name to find
1447 *              - pointer to username to find
1448 *              - pointer to host to find
1449 * output       - NULL or pointer to conf found
1450 * side effects - find a conf entry which matches the hostname
1451 *                and has the same name.
1452 */
1453 struct ConfItem *
1454 find_conf_exact(ConfType type, const char *name, const char *user,
1455                const char *host)
1456 {
1457  dlink_node *ptr;
1458  dlink_list *list_p;
1459  struct ConfItem *conf = NULL;
1460  struct AccessItem *aconf;
1461
1462  /* Only valid for OPER_TYPE and ...? */
1463  list_p = map_to_list(type);
1464
1465  DLINK_FOREACH(ptr, (*list_p).head)
1466  {
1467    conf = ptr->data;
1468
1469    if (conf->name == NULL)
1470      continue;
1471    aconf = map_to_conf(conf);
1472    if (aconf->host == NULL)
1473      continue;
1474    if (irccmp(conf->name, name) != 0)
1475      continue;
1476
1477    /*
1478    ** Accept if the *real* hostname (usually sockethost)
1479    ** socket host) matches *either* host or name field
1480    ** of the configuration.
1481    */
1482    if (!match(aconf->host, host) || !match(aconf->user, user))
1483      continue;
1484    if (type == OPER_TYPE)
1485    {
1486      struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1487
1488      if (aconf->clients >= MaxTotal(aclass))
1489        continue;
1490    }
1491
1492    return conf;
1493  }
1494
1495  return NULL;
1496 }
1497
764   /* find_conf_name()
765   *
766   * inputs       - pointer to conf link list to search
# Line 1504 | Line 770 | find_conf_exact(ConfType type, const cha
770   * side effects - find a conf entry which matches the name
771   *                and has the given mask.
772   */
773 < struct ConfItem *
774 < find_conf_name(dlink_list *list, const char *name, ConfType type)
773 > struct MaskItem *
774 > find_conf_name(dlink_list *list, const char *name, enum maskitem_type type)
775   {
776    dlink_node *ptr;
777 <  struct ConfItem* conf;
777 >  struct MaskItem* conf;
778  
779    DLINK_FOREACH(ptr, list->head)
780    {
781      conf = ptr->data;
782 <    
782 >
783      if (conf->type == type)
784      {
785 <      if (conf->name && (irccmp(conf->name, name) == 0 ||
786 <                         match(conf->name, name)))
785 >      if (conf->name && (!irccmp(conf->name, name) ||
786 >                         !match(conf->name, name)))
787        return conf;
788      }
789    }
# Line 1532 | Line 798 | find_conf_name(dlink_list *list, const c
798   * side effects - none
799   */
800   static dlink_list *
801 < map_to_list(ConfType type)
801 > map_to_list(enum maskitem_type type)
802   {
803    switch(type)
804    {
805 <  case RXLINE_TYPE:
1540 <    return(&rxconf_items);
1541 <    break;
1542 <  case XLINE_TYPE:
805 >  case CONF_XLINE:
806      return(&xconf_items);
807      break;
808 <  case ULINE_TYPE:
808 >  case CONF_ULINE:
809      return(&uconf_items);
810      break;
811 <  case NRESV_TYPE:
811 >  case CONF_NRESV:
812      return(&nresv_items);
813      break;
814 <  case OPER_TYPE:
814 >  case CONF_CRESV:
815 >    return(&cresv_items);
816 >  case CONF_OPER:
817      return(&oconf_items);
818      break;
819 <  case CLASS_TYPE:
1555 <    return(&class_items);
1556 <    break;
1557 <  case SERVER_TYPE:
819 >  case CONF_SERVER:
820      return(&server_items);
821      break;
822 <  case SERVICE_TYPE:
822 >  case CONF_SERVICE:
823      return(&service_items);
824      break;
825 <  case CLUSTER_TYPE:
825 >  case CONF_CLUSTER:
826      return(&cluster_items);
827      break;
1566  case CONF_TYPE:
1567  case GLINE_TYPE:
1568  case KLINE_TYPE:
1569  case DLINE_TYPE:
1570  case CRESV_TYPE:
828    default:
829      return NULL;
830    }
# Line 1579 | Line 836 | map_to_list(ConfType type)
836   *              - pointer to name string to find
837   *              - pointer to user
838   *              - pointer to host
839 < *              - optional action to match on as well
840 < * output       - NULL or pointer to found struct MatchItem
839 > *              - optional flags to match on as well
840 > * output       - NULL or pointer to found struct MaskItem
841   * side effects - looks for a match on name field
842   */
843 < struct ConfItem *
844 < find_matching_name_conf(ConfType type, const char *name, const char *user,
845 <                        const char *host, int action)
843 > struct MaskItem *
844 > find_matching_name_conf(enum maskitem_type type, const char *name, const char *user,
845 >                        const char *host, unsigned int flags)
846   {
847    dlink_node *ptr=NULL;
848 <  struct ConfItem *conf=NULL;
1592 <  struct AccessItem *aconf=NULL;
1593 <  struct MatchItem *match_item=NULL;
848 >  struct MaskItem *conf=NULL;
849    dlink_list *list_p = map_to_list(type);
850  
851    switch (type)
852    {
853 < #ifdef HAVE_LIBPCRE
1599 <  case RXLINE_TYPE:
1600 <      DLINK_FOREACH(ptr, list_p->head)
1601 <      {
1602 <        conf = ptr->data;
1603 <        assert(conf->regexpname);
1604 <
1605 <        if (!ircd_pcre_exec(conf->regexpname, name))
1606 <          return conf;
1607 <      }
1608 <      break;
1609 < #endif
1610 <  case SERVICE_TYPE:
853 >  case CONF_SERVICE:
854      DLINK_FOREACH(ptr, list_p->head)
855      {
856        conf = ptr->data;
# Line 1619 | Line 862 | find_matching_name_conf(ConfType type, c
862      }
863      break;
864  
865 <  case XLINE_TYPE:
866 <  case ULINE_TYPE:
867 <  case NRESV_TYPE:
865 >  case CONF_XLINE:
866 >  case CONF_ULINE:
867 >  case CONF_NRESV:
868 >  case CONF_CRESV:
869      DLINK_FOREACH(ptr, list_p->head)
870      {
871        conf = ptr->data;
872  
1629      match_item = map_to_conf(conf);
873        if (EmptyString(conf->name))
874 <        continue;
875 <      if ((name != NULL) && match_esc(conf->name, name))
874 >        continue;
875 >      if ((name != NULL) && !match(conf->name, name))
876        {
877 <        if ((user == NULL && (host == NULL)))
878 <          return conf;
879 <        if ((match_item->action & action) != action)
877 >        if ((user == NULL && (host == NULL)))
878 >          return conf;
879 >        if ((conf->flags & flags) != flags)
880            continue;
881 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
882 <          return conf;
883 <        if (match(match_item->user, user) && match(match_item->host, host))
884 <          return conf;
881 >        if (EmptyString(conf->user) || EmptyString(conf->host))
882 >          return conf;
883 >        if (!match(conf->user, user) && !match(conf->host, host))
884 >          return conf;
885        }
886      }
887        break;
888  
889 <  case SERVER_TYPE:
889 >  case CONF_SERVER:
890      DLINK_FOREACH(ptr, list_p->head)
891      {
892        conf = ptr->data;
1650      aconf = map_to_conf(conf);
893  
894 <      if ((name != NULL) && match_esc(name, conf->name))
894 >      if ((name != NULL) && !match(name, conf->name))
895          return conf;
896 <      else if ((host != NULL) && match_esc(host, aconf->host))
896 >      else if ((host != NULL) && !match(host, conf->host))
897          return conf;
898      }
899      break;
900 <  
900 >
901    default:
902      break;
903    }
# Line 1668 | Line 910 | find_matching_name_conf(ConfType type, c
910   *              - pointer to name string to find
911   *              - pointer to user
912   *              - pointer to host
913 < * output       - NULL or pointer to found struct MatchItem
913 > * output       - NULL or pointer to found struct MaskItem
914   * side effects - looks for an exact match on name field
915   */
916 < struct ConfItem *
917 < find_exact_name_conf(ConfType type, const char *name,
916 > struct MaskItem *
917 > find_exact_name_conf(enum maskitem_type type, const struct Client *who, const char *name,
918                       const char *user, const char *host)
919   {
920    dlink_node *ptr = NULL;
921 <  struct AccessItem *aconf;
922 <  struct ConfItem *conf;
1681 <  struct MatchItem *match_item;
1682 <  dlink_list *list_p;
1683 <
1684 <  list_p = map_to_list(type);
921 >  struct MaskItem *conf;
922 >  dlink_list *list_p = map_to_list(type);
923  
924    switch(type)
925    {
926 <  case RXLINE_TYPE:
927 <  case XLINE_TYPE:
928 <  case ULINE_TYPE:
929 <  case NRESV_TYPE:
926 >  case CONF_XLINE:
927 >  case CONF_ULINE:
928 >  case CONF_NRESV:
929 >  case CONF_CRESV:
930  
931      DLINK_FOREACH(ptr, list_p->head)
932      {
933        conf = ptr->data;
934 <      match_item = (struct MatchItem *)map_to_conf(conf);
934 >
935        if (EmptyString(conf->name))
936 <        continue;
937 <    
936 >        continue;
937 >
938        if (irccmp(conf->name, name) == 0)
939        {
940 <        if ((user == NULL && (host == NULL)))
941 <          return (conf);
942 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
943 <          return (conf);
944 <        if (match(match_item->user, user) && match(match_item->host, host))
945 <          return (conf);
940 >        if ((user == NULL && (host == NULL)))
941 >          return conf;
942 >        if (EmptyString(conf->user) || EmptyString(conf->host))
943 >          return conf;
944 >        if (!match(conf->user, user) && !match(conf->host, host))
945 >          return conf;
946        }
947      }
948      break;
949  
950 <  case OPER_TYPE:
950 >  case CONF_OPER:
951      DLINK_FOREACH(ptr, list_p->head)
952      {
953        conf = ptr->data;
954 <      aconf = (struct AccessItem *)map_to_conf(conf);
954 >
955        if (EmptyString(conf->name))
956 <        continue;
957 <    
958 <      if (irccmp(conf->name, name) == 0)
956 >        continue;
957 >
958 >      if (!irccmp(conf->name, name))
959        {
960 <        if ((user == NULL && (host == NULL)))
961 <          return (conf);
962 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
963 <          return (conf);
964 <        if (match(aconf->user, user) && match(aconf->host, host))
965 <          return (conf);
960 >        if (!who)
961 >          return conf;
962 >        if (EmptyString(conf->user) || EmptyString(conf->host))
963 >          return NULL;
964 >        if (!match(conf->user, who->username))
965 >        {
966 >          switch (conf->htype)
967 >          {
968 >            case HM_HOST:
969 >              if (!match(conf->host, who->host) || !match(conf->host, who->sockhost))
970 >                if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
971 >                  return conf;
972 >              break;
973 >            case HM_IPV4:
974 >              if (who->localClient->aftype == AF_INET)
975 >                if (match_ipv4(&who->localClient->ip, &conf->addr, conf->bits))
976 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
977 >                    return conf;
978 >              break;
979 > #ifdef IPV6
980 >            case HM_IPV6:
981 >              if (who->localClient->aftype == AF_INET6)
982 >                if (match_ipv6(&who->localClient->ip, &conf->addr, conf->bits))
983 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
984 >                    return conf;
985 >              break;
986 > #endif
987 >            default:
988 >              assert(0);
989 >          }
990 >        }
991        }
992      }
993 +
994      break;
995  
996 <  case SERVER_TYPE:
996 >  case CONF_SERVER:
997      DLINK_FOREACH(ptr, list_p->head)
998      {
999        conf = ptr->data;
1000 <      aconf = (struct AccessItem *)map_to_conf(conf);
1000 >
1001        if (EmptyString(conf->name))
1002 <        continue;
1003 <    
1002 >        continue;
1003 >
1004        if (name == NULL)
1005        {
1006 <        if (EmptyString(aconf->host))
1007 <          continue;
1008 <        if (irccmp(aconf->host, host) == 0)
1009 <          return(conf);
1006 >        if (EmptyString(conf->host))
1007 >          continue;
1008 >        if (irccmp(conf->host, host) == 0)
1009 >          return conf;
1010        }
1011        else if (irccmp(conf->name, name) == 0)
1012 <      {
1749 <          return (conf);
1750 <      }
1012 >        return conf;
1013      }
1752    break;
1014  
1754  case CLASS_TYPE:
1755    DLINK_FOREACH(ptr, list_p->head)
1756    {
1757      conf = ptr->data;
1758      if (EmptyString(conf->name))
1759        continue;
1760    
1761      if (irccmp(conf->name, name) == 0)
1762        return (conf);
1763    }
1015      break;
1016  
1017    default:
1018      break;
1019    }
1020 <  return(NULL);
1020 >
1021 >  return NULL;
1022   }
1023  
1024   /* rehash()
# Line 1778 | Line 1030 | find_exact_name_conf(ConfType type, cons
1030   int
1031   rehash(int sig)
1032   {
1033 <  if (sig != 0)
1034 <    sendto_realops_flags(UMODE_ALL, L_ALL,
1035 <                         "Got signal SIGHUP, reloading ircd.conf file");
1033 >  if (sig)
1034 >    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1035 >                         "Got signal SIGHUP, reloading configuration file(s)");
1036  
1037    restart_resolver();
1038  
# Line 1791 | Line 1043 | rehash(int sig)
1043  
1044    read_conf_files(0);
1045  
1046 <  if (ServerInfo.description != NULL)
1046 >  if (ServerInfo.description)
1047      strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1048  
1049    load_conf_modules();
1050 +  check_conf_klines();
1051  
1052 <  flush_deleted_I_P();
1800 <
1801 <  rehashed_klines = 1;
1802 <
1803 <  if (ConfigLoggingEntry.use_logging)
1804 <    reopen_log(logFileName);
1805 <
1806 <  return(0);
1052 >  return 0;
1053   }
1054  
1055   /* set_default_conf()
# Line 1821 | Line 1067 | set_default_conf(void)
1067    /* verify init_class() ran, this should be an unnecessary check
1068     * but its not much work.
1069     */
1070 <  assert(class_default == (struct ConfItem *) class_items.tail->data);
1070 >  assert(class_default == class_get_list()->tail->data);
1071  
1072   #ifdef HAVE_LIBCRYPTO
1073    ServerInfo.rsa_private_key = NULL;
# Line 1831 | Line 1077 | set_default_conf(void)
1077    /* ServerInfo.name is not rehashable */
1078    /* ServerInfo.name = ServerInfo.name; */
1079    ServerInfo.description = NULL;
1080 <  DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1081 <  DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1080 >  ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1081 >  ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1082  
1083    memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1084    ServerInfo.specific_ipv4_vhost = 0;
# Line 1840 | Line 1086 | set_default_conf(void)
1086    ServerInfo.specific_ipv6_vhost = 0;
1087  
1088    ServerInfo.max_clients = MAXCLIENTS_MAX;
1089 +  ServerInfo.max_nick_length = 9;
1090 +  ServerInfo.max_topic_length = 80;
1091  
1092    ServerInfo.hub = 0;
1093    ServerInfo.dns_host.sin_addr.s_addr = 0;
# Line 1848 | Line 1096 | set_default_conf(void)
1096    AdminInfo.email = NULL;
1097    AdminInfo.description = NULL;
1098  
1099 <  set_log_level(L_NOTICE);
1099 >  log_del_all();
1100 >
1101    ConfigLoggingEntry.use_logging = 1;
1102 <  ConfigLoggingEntry.operlog[0] = '\0';
1103 <  ConfigLoggingEntry.userlog[0] = '\0';
1104 <  ConfigLoggingEntry.klinelog[0] = '\0';
1105 <  ConfigLoggingEntry.glinelog[0] = '\0';
1106 <  ConfigLoggingEntry.killlog[0] = '\0';
1107 <  ConfigLoggingEntry.operspylog[0] = '\0';
1859 <  ConfigLoggingEntry.ioerrlog[0] = '\0';
1860 <  ConfigLoggingEntry.failed_operlog[0] = '\0';
1861 <
1862 <  ConfigChannel.disable_fake_channels = NO;
1863 <  ConfigChannel.restrict_channels = NO;
1864 <  ConfigChannel.disable_local_channels = NO;
1865 <  ConfigChannel.use_invex = YES;
1866 <  ConfigChannel.use_except = YES;
1867 <  ConfigChannel.use_knock = YES;
1868 <  ConfigChannel.knock_delay = 300;
1102 >
1103 >  ConfigChannel.disable_fake_channels = 0;
1104 >  ConfigChannel.invite_client_count = 10;
1105 >  ConfigChannel.invite_client_time = 300;
1106 >  ConfigChannel.knock_client_count = 1;
1107 >  ConfigChannel.knock_client_time = 300;
1108    ConfigChannel.knock_delay_channel = 60;
1109 <  ConfigChannel.max_chans_per_user = 15;
1871 <  ConfigChannel.quiet_on_ban = YES;
1109 >  ConfigChannel.max_channels = 25;
1110    ConfigChannel.max_bans = 25;
1111    ConfigChannel.default_split_user_count = 0;
1112    ConfigChannel.default_split_server_count = 0;
1113 <  ConfigChannel.no_join_on_split = NO;
1114 <  ConfigChannel.no_create_on_split = NO;
1877 <  ConfigChannel.burst_topicwho = YES;
1113 >  ConfigChannel.no_join_on_split = 0;
1114 >  ConfigChannel.no_create_on_split = 0;
1115  
1116 <  ConfigServerHide.flatten_links = NO;
1116 >  ConfigServerHide.flatten_links = 0;
1117    ConfigServerHide.links_delay = 300;
1118 <  ConfigServerHide.hidden = NO;
1119 <  ConfigServerHide.disable_hidden = NO;
1120 <  ConfigServerHide.hide_servers = NO;
1121 <  DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1122 <  ConfigServerHide.hide_server_ips = NO;
1118 >  ConfigServerHide.hidden = 0;
1119 >  ConfigServerHide.hide_servers = 0;
1120 >  ConfigServerHide.hide_services = 0;
1121 >  ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
1122 >  ConfigServerHide.hide_server_ips = 0;
1123 >  ConfigServerHide.disable_remote_commands = 0;
1124  
1125 <  
1888 <  DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1125 >  ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1126    ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1127 +  ConfigFileEntry.cycle_on_host_change = 1;
1128 +  ConfigFileEntry.glines = 0;
1129 +  ConfigFileEntry.gline_time = 12 * 3600;
1130 +  ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
1131    ConfigFileEntry.gline_min_cidr = 16;
1132    ConfigFileEntry.gline_min_cidr6 = 48;
1133 <  ConfigFileEntry.invisible_on_connect = YES;
1134 <  ConfigFileEntry.burst_away = NO;
1135 <  ConfigFileEntry.use_whois_actually = YES;
1136 <  ConfigFileEntry.tkline_expire_notices = YES;
1137 <  ConfigFileEntry.hide_spoof_ips = YES;
1897 <  ConfigFileEntry.ignore_bogus_ts = NO;
1898 <  ConfigFileEntry.disable_auth = NO;
1899 <  ConfigFileEntry.disable_remote = NO;
1133 >  ConfigFileEntry.invisible_on_connect = 1;
1134 >  ConfigFileEntry.tkline_expire_notices = 1;
1135 >  ConfigFileEntry.hide_spoof_ips = 1;
1136 >  ConfigFileEntry.ignore_bogus_ts = 0;
1137 >  ConfigFileEntry.disable_auth = 0;
1138    ConfigFileEntry.kill_chase_time_limit = 90;
1139    ConfigFileEntry.default_floodcount = 8;
1140 <  ConfigFileEntry.failed_oper_notice = YES;
1140 >  ConfigFileEntry.failed_oper_notice = 1;
1141    ConfigFileEntry.dots_in_ident = 0;
1142    ConfigFileEntry.min_nonwildcard = 4;
1143    ConfigFileEntry.min_nonwildcard_simple = 3;
1144    ConfigFileEntry.max_accept = 20;
1145 <  ConfigFileEntry.anti_nick_flood = NO;
1145 >  ConfigFileEntry.anti_nick_flood = 0;
1146    ConfigFileEntry.max_nick_time = 20;
1147    ConfigFileEntry.max_nick_changes = 5;
1148    ConfigFileEntry.anti_spam_exit_message_time = 0;
1149    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1150    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1151 <  ConfigFileEntry.kline_with_reason = YES;
1152 <  ConfigFileEntry.kline_reason = NULL;
1153 <  ConfigFileEntry.warn_no_nline = YES;
1154 <  ConfigFileEntry.stats_o_oper_only = NO;
1155 <  ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
1156 <  ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
1157 <  ConfigFileEntry.stats_P_oper_only = NO;
1151 >  ConfigFileEntry.warn_no_connect_block = 1;
1152 >  ConfigFileEntry.stats_e_disabled = 0;
1153 >  ConfigFileEntry.stats_o_oper_only = 0;
1154 >  ConfigFileEntry.stats_k_oper_only = 1;  /* 1 = masked */
1155 >  ConfigFileEntry.stats_i_oper_only = 1;  /* 1 = masked */
1156 >  ConfigFileEntry.stats_P_oper_only = 0;
1157 >  ConfigFileEntry.stats_u_oper_only = 0;
1158    ConfigFileEntry.caller_id_wait = 60;
1159 <  ConfigFileEntry.opers_bypass_callerid = NO;
1159 >  ConfigFileEntry.opers_bypass_callerid = 0;
1160    ConfigFileEntry.pace_wait = 10;
1161    ConfigFileEntry.pace_wait_simple = 1;
1162 <  ConfigFileEntry.short_motd = NO;
1163 <  ConfigFileEntry.ping_cookie = NO;
1164 <  ConfigFileEntry.no_oper_flood = NO;
1165 <  ConfigFileEntry.true_no_oper_flood = NO;
1166 <  ConfigFileEntry.oper_pass_resv = YES;
1929 <  ConfigFileEntry.glines = NO;
1930 <  ConfigFileEntry.gline_time = 12 * 3600;
1162 >  ConfigFileEntry.short_motd = 0;
1163 >  ConfigFileEntry.ping_cookie = 0;
1164 >  ConfigFileEntry.no_oper_flood = 0;
1165 >  ConfigFileEntry.true_no_oper_flood = 0;
1166 >  ConfigFileEntry.oper_pass_resv = 1;
1167    ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1932  ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1168    ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1169 <  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1170 <    UMODE_OPERWALL | UMODE_WALLOP;
1936 <  DupString(ConfigFileEntry.servlink_path, SLPATH);
1937 < #ifdef HAVE_LIBCRYPTO
1938 <  /* jdc -- This is our default value for a cipher.  According to the
1939 <   *        CRYPTLINK document (doc/cryptlink.txt), BF/128 must be supported
1940 <   *        under all circumstances if cryptlinks are enabled.  So,
1941 <   *        this will be our default.
1942 <   *
1943 <   *        NOTE: I apologise for the hard-coded value of "1" (BF/128).
1944 <   *              This should be moved into a find_cipher() routine.
1945 <   */
1946 <  ConfigFileEntry.default_cipher_preference = &CipherTable[1];
1947 < #endif
1948 <  ConfigFileEntry.use_egd = NO;
1169 >  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE | UMODE_WALLOP;
1170 >  ConfigFileEntry.use_egd = 0;
1171    ConfigFileEntry.egdpool_path = NULL;
1172 < #ifdef HAVE_LIBZ
1951 <  ConfigFileEntry.compression_level = 0;
1952 < #endif
1172 >  ConfigFileEntry.throttle_count = 0;
1173    ConfigFileEntry.throttle_time = 10;
1174   }
1175  
1956 /* read_conf()
1957 *
1958 * inputs       - file descriptor pointing to config file to use
1959 * output       - None
1960 * side effects - Read configuration file.
1961 */
1962 static void
1963 read_conf(FBFILE *file)
1964 {
1965  lineno = 0;
1966
1967  set_default_conf(); /* Set default values prior to conf parsing */
1968  conf_parser_ctx.pass = 1;
1969  yyparse();          /* pick up the classes first */
1970
1971  fbrewind(file);
1972
1973  conf_parser_ctx.pass = 2;
1974  yyparse();          /* Load the values from the conf */
1975  validate_conf();    /* Check to make sure some values are still okay. */
1976                      /* Some global values are also loaded here. */
1977  check_class();      /* Make sure classes are valid */
1978 }
1979
1176   static void
1177   validate_conf(void)
1178   {
# Line 1986 | Line 1182 | validate_conf(void)
1182    if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1183      ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1184  
1989  if (ConfigFileEntry.servlink_path == NULL)
1990    DupString(ConfigFileEntry.servlink_path, SLPATH);
1991
1185    if (ServerInfo.network_name == NULL)
1186 <    DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1186 >    ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1187  
1188    if (ServerInfo.network_desc == NULL)
1189 <    DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1189 >    ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1190  
1191    if (ConfigFileEntry.service_name == NULL)
1192 <    DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
2000 <
2001 <  if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
2002 <      (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
2003 <    ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1192 >    ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1193  
1194    ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1195   }
1196  
1197 < /* lookup_confhost()
1197 > /* read_conf()
1198   *
1199 < * start DNS lookups of all hostnames in the conf
1200 < * line and convert an IP addresses in a.b.c.d number for to IP#s.
1199 > * inputs       - file descriptor pointing to config file to use
1200 > * output       - None
1201 > * side effects - Read configuration file.
1202   */
1203   static void
1204 < lookup_confhost(struct ConfItem *conf)
1204 > read_conf(FILE *file)
1205   {
1206 <  struct AccessItem *aconf;
2017 <  struct addrinfo hints, *res;
1206 >  lineno = 0;
1207  
1208 <  aconf = map_to_conf(conf);
1208 >  set_default_conf();  /* Set default values prior to conf parsing */
1209 >  conf_parser_ctx.pass = 1;
1210 >  yyparse();  /* Pick up the classes first */
1211  
1212 <  if (EmptyString(aconf->host) ||
2022 <      EmptyString(aconf->user))
2023 <  {
2024 <    ilog(L_ERROR, "Host/server name error: (%s) (%s)",
2025 <         aconf->host, conf->name);
2026 <    return;
2027 <  }
1212 >  rewind(file);
1213  
1214 <  if (strchr(aconf->host, '*') ||
1215 <      strchr(aconf->host, '?'))
1216 <    return;
1214 >  conf_parser_ctx.pass = 2;
1215 >  yyparse();  /* Load the values from the conf */
1216 >  validate_conf();  /* Check to make sure some values are still okay. */
1217 >                    /* Some global values are also loaded here. */
1218 >  class_delete_marked();  /* Delete unused classes that are marked for deletion */
1219 > }
1220  
1221 <  /* Do name lookup now on hostnames given and store the
1221 > /* lookup_confhost()
1222 > *
1223 > * start DNS lookups of all hostnames in the conf
1224 > * line and convert an IP addresses in a.b.c.d number for to IP#s.
1225 > */
1226 > void
1227 > lookup_confhost(struct MaskItem *conf)
1228 > {
1229 >  struct addrinfo hints, *res;
1230 >
1231 >  /*
1232 >   * Do name lookup now on hostnames given and store the
1233     * ip numbers in conf structure.
1234     */
1235    memset(&hints, 0, sizeof(hints));
# Line 2041 | Line 1240 | lookup_confhost(struct ConfItem *conf)
1240    /* Get us ready for a bind() and don't bother doing dns lookup */
1241    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1242  
1243 <  if (getaddrinfo(aconf->host, NULL, &hints, &res))
1243 >  if (getaddrinfo(conf->host, NULL, &hints, &res))
1244    {
1245 <    conf_dns_lookup(aconf);
1245 >    conf_dns_lookup(conf);
1246      return;
1247    }
1248  
1249 <  assert(res != NULL);
1249 >  assert(res);
1250 >
1251 >  memcpy(&conf->addr, res->ai_addr, res->ai_addrlen);
1252 >  conf->addr.ss_len = res->ai_addrlen;
1253 >  conf->addr.ss.ss_family = res->ai_family;
1254  
2052  memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
2053  aconf->ipnum.ss_len = res->ai_addrlen;
2054  aconf->ipnum.ss.ss_family = res->ai_family;
1255    freeaddrinfo(res);
1256   }
1257  
# Line 2065 | Line 1265 | lookup_confhost(struct ConfItem *conf)
1265   int
1266   conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1267   {
1268 <  struct ip_entry *ip_found;
1269 <  struct AccessItem *aconf = find_dline_conf(addr, aftype);
1268 >  struct ip_entry *ip_found = NULL;
1269 >  struct MaskItem *conf = find_dline_conf(addr, aftype);
1270  
1271    /* DLINE exempt also gets you out of static limits/pacing... */
1272 <  if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1272 >  if (conf && (conf->type == CONF_EXEMPT))
1273      return 0;
1274  
1275 <  if (aconf != NULL)
1275 >  if (conf)
1276      return BANNED_CLIENT;
1277  
1278    ip_found = find_or_add_ip(addr);
1279 +  ++ip_found->connection_count;
1280  
1281 <  if ((CurrentTime - ip_found->last_attempt) <
2081 <      ConfigFileEntry.throttle_time)
1281 >  if ((CurrentTime - ip_found->last_attempt) < ConfigFileEntry.throttle_time)
1282    {
1283 <    ip_found->last_attempt = CurrentTime;
1284 <    return TOO_FAST;
1283 >    if (ip_found->connection_count >= ConfigFileEntry.throttle_count)
1284 >    {
1285 >      ip_found->last_attempt = CurrentTime;
1286 >      return TOO_FAST;
1287 >    }
1288    }
1289 +  else
1290 +    ip_found->connection_count = 1;
1291  
1292    ip_found->last_attempt = CurrentTime;
1293    return 0;
1294   }
1295  
2091 static struct AccessItem *
2092 find_regexp_kline(const char *uhi[])
2093 {
2094 #ifdef HAVE_LIBPCRE
2095  const dlink_node *ptr = NULL;
2096
2097  DLINK_FOREACH(ptr, rkconf_items.head)
2098  {
2099    struct AccessItem *aptr = map_to_conf(ptr->data);
2100
2101    assert(aptr->regexuser);
2102    assert(aptr->regexhost);
2103
2104    if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2105        (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2106         !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2107      return aptr;
2108  }
2109 #endif
2110  return NULL;
2111 }
2112
2113 /* find_kill()
2114 *
2115 * inputs       - pointer to client structure
2116 * output       - pointer to struct AccessItem if found
2117 * side effects - See if this user is klined already,
2118 *                and if so, return struct AccessItem pointer
2119 */
2120 struct AccessItem *
2121 find_kill(struct Client *client_p)
2122 {
2123  struct AccessItem *aconf = NULL;
2124  const char *uhi[3];
2125
2126  uhi[0] = client_p->username;
2127  uhi[1] = client_p->host;
2128  uhi[2] = client_p->sockhost;
2129
2130  assert(client_p != NULL);
2131
2132  aconf = find_kline_conf(client_p->host, client_p->username,
2133                          &client_p->localClient->ip,
2134                          client_p->localClient->aftype);
2135  if (aconf == NULL)
2136    aconf = find_regexp_kline(uhi);
2137
2138  if (aconf && (aconf->status & CONF_KLINE))
2139    return aconf;
2140
2141  return NULL;
2142 }
2143
2144 struct AccessItem *
2145 find_gline(struct Client *client_p)
2146 {
2147  struct AccessItem *aconf;
2148
2149  assert(client_p != NULL);
2150
2151  aconf = find_gline_conf(client_p->host, client_p->username,
2152                          &client_p->localClient->ip,
2153                          client_p->localClient->aftype);
2154
2155  if (aconf && (aconf->status & CONF_GLINE))
2156    return aconf;
2157
2158  return NULL;
2159 }
2160
2161 /* add_temp_line()
2162 *
2163 * inputs        - pointer to struct ConfItem
2164 * output        - none
2165 * Side effects  - links in given struct ConfItem into
2166 *                 temporary *line link list
2167 */
2168 void
2169 add_temp_line(struct ConfItem *conf)
2170 {
2171  struct AccessItem *aconf;
2172
2173  if (conf->type == DLINE_TYPE)
2174  {
2175    aconf = map_to_conf(conf);
2176    SetConfTemporary(aconf);
2177    dlinkAdd(conf, &conf->node, &temporary_dlines);
2178    MyFree(aconf->user);
2179    aconf->user = NULL;
2180    add_conf_by_address(CONF_DLINE, aconf);
2181  }
2182  else if (conf->type == KLINE_TYPE)
2183  {
2184    aconf = map_to_conf(conf);
2185    SetConfTemporary(aconf);
2186    dlinkAdd(conf, &conf->node, &temporary_klines);
2187    add_conf_by_address(CONF_KILL, aconf);
2188  }
2189  else if (conf->type == GLINE_TYPE)
2190  {
2191    aconf = map_to_conf(conf);
2192    SetConfTemporary(aconf);
2193    dlinkAdd(conf, &conf->node, &temporary_glines);
2194    add_conf_by_address(CONF_GLINE, aconf);
2195  }
2196  else if (conf->type == XLINE_TYPE)
2197  {
2198    conf->flags |= CONF_FLAGS_TEMPORARY;
2199    dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2200  }
2201  else if (conf->type == RXLINE_TYPE)
2202  {
2203    conf->flags |= CONF_FLAGS_TEMPORARY;
2204    dlinkAdd(conf, make_dlink_node(), &temporary_rxlines);
2205  }
2206  else if (conf->type == RKLINE_TYPE)
2207  {
2208    conf->flags |= CONF_FLAGS_TEMPORARY;
2209    dlinkAdd(conf, make_dlink_node(), &temporary_rklines);
2210  }
2211  else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2212  {
2213    conf->flags |= CONF_FLAGS_TEMPORARY;
2214    dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2215  }
2216 }
2217
1296   /* cleanup_tklines()
1297   *
1298   * inputs       - NONE
# Line 2225 | Line 1303 | add_temp_line(struct ConfItem *conf)
1303   void
1304   cleanup_tklines(void *notused)
1305   {
1306 <  expire_tklines(&temporary_glines);
1307 <  expire_tklines(&temporary_klines);
1308 <  expire_tklines(&temporary_dlines);
1309 <  expire_tklines(&temporary_xlines);
2232 <  expire_tklines(&temporary_rxlines);
2233 <  expire_tklines(&temporary_rklines);
2234 <  expire_tklines(&temporary_resv);
1306 >  hostmask_expire_temporary();
1307 >  expire_tklines(&xconf_items);
1308 >  expire_tklines(&nresv_items);
1309 >  expire_tklines(&cresv_items);
1310   }
1311  
1312   /* expire_tklines()
# Line 2243 | Line 1318 | cleanup_tklines(void *notused)
1318   static void
1319   expire_tklines(dlink_list *tklist)
1320   {
1321 <  dlink_node *ptr;
1322 <  dlink_node *next_ptr;
2248 <  struct ConfItem *conf;
2249 <  struct MatchItem *xconf;
2250 <  struct MatchItem *nconf;
2251 <  struct AccessItem *aconf;
2252 <  struct ResvChannel *cconf;
1321 >  dlink_node *ptr = NULL, *ptr_next = NULL;
1322 >  struct MaskItem *conf = NULL;
1323  
1324 <  DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
1324 >  DLINK_FOREACH_SAFE(ptr, ptr_next, tklist->head)
1325    {
1326      conf = ptr->data;
2257    if (conf->type == GLINE_TYPE ||
2258        conf->type == KLINE_TYPE ||
2259        conf->type == DLINE_TYPE)
2260    {
2261      aconf = (struct AccessItem *)map_to_conf(conf);
2262      if (aconf->hold <= CurrentTime)
2263      {
2264        /* XXX - Do we want GLINE expiry notices?? */
2265        /* Alert opers that a TKline expired - Hwy */
2266        if (ConfigFileEntry.tkline_expire_notices)
2267        {
2268          if (aconf->status & CONF_KILL)
2269          {
2270            sendto_realops_flags(UMODE_ALL, L_ALL,
2271                                 "Temporary K-line for [%s@%s] expired",
2272                                 (aconf->user) ? aconf->user : "*",
2273                                 (aconf->host) ? aconf->host : "*");
2274          }
2275          else if (conf->type == DLINE_TYPE)
2276          {
2277            sendto_realops_flags(UMODE_ALL, L_ALL,
2278                                 "Temporary D-line for [%s] expired",
2279                                 (aconf->host) ? aconf->host : "*");
2280          }
2281        }
1327  
1328 <        dlinkDelete(ptr, tklist);
1329 <        delete_one_address_conf(aconf->host, aconf);
1330 <      }
1331 <    }
2287 <    else if (conf->type == XLINE_TYPE ||
2288 <             conf->type == RXLINE_TYPE)
2289 <    {
2290 <      xconf = (struct MatchItem *)map_to_conf(conf);
2291 <      if (xconf->hold <= CurrentTime)
2292 <      {
2293 <        if (ConfigFileEntry.tkline_expire_notices)
2294 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2295 <                               "Temporary X-line for [%s] %sexpired", conf->name,
2296 <                               conf->type == RXLINE_TYPE ? "(REGEX) " : "");
2297 <        dlinkDelete(ptr, tklist);
2298 <        free_dlink_node(ptr);
2299 <        delete_conf_item(conf);
2300 <      }
2301 <    }
2302 <    else if (conf->type == RKLINE_TYPE)
1328 >    if (!conf->until || conf->until > CurrentTime)
1329 >      continue;
1330 >
1331 >    if (conf->type == CONF_XLINE)
1332      {
1333 <      aconf = map_to_conf(conf);
1334 <      if (aconf->hold <= CurrentTime)
1335 <      {
1336 <        if (ConfigFileEntry.tkline_expire_notices)
2308 <           sendto_realops_flags(UMODE_ALL, L_ALL,
2309 <                                "Temporary K-line for [%s@%s] (REGEX) expired",
2310 <                                (aconf->user) ? aconf->user : "*",
2311 <                                (aconf->host) ? aconf->host : "*");
2312 <        dlinkDelete(ptr, tklist);
2313 <        free_dlink_node(ptr);
2314 <        delete_conf_item(conf);
2315 <      }
1333 >      if (ConfigFileEntry.tkline_expire_notices)
1334 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1335 >                               "Temporary X-line for [%s] expired", conf->name);
1336 >      conf_free(conf);
1337      }
1338 <    else if (conf->type == NRESV_TYPE)
1338 >    else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1339      {
1340 <      nconf = (struct MatchItem *)map_to_conf(conf);
1341 <      if (nconf->hold <= CurrentTime)
2321 <      {
2322 <        if (ConfigFileEntry.tkline_expire_notices)
2323 <          sendto_realops_flags(UMODE_ALL, L_ALL,
1340 >      if (ConfigFileEntry.tkline_expire_notices)
1341 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1342                                 "Temporary RESV for [%s] expired", conf->name);
1343 <        dlinkDelete(ptr, tklist);
2326 <        free_dlink_node(ptr);
2327 <        delete_conf_item(conf);
2328 <      }
2329 <    }
2330 <    else if (conf->type == CRESV_TYPE)
2331 <    {
2332 <      cconf = (struct ResvChannel *)map_to_conf(conf);
2333 <      if (cconf->hold <= CurrentTime)
2334 <      {
2335 <        if (ConfigFileEntry.tkline_expire_notices)
2336 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2337 <                               "Temporary RESV for [%s] expired", cconf->name);
2338 <        delete_channel_resv(cconf);
2339 <      }
1343 >      conf_free(conf);
1344      }
1345    }
1346   }
# Line 2349 | Line 1353 | expire_tklines(dlink_list *tklist)
1353   */
1354   static const struct oper_privs
1355   {
1356 <  const unsigned int oprivs;
2353 <  const unsigned int hidden;
1356 >  const unsigned int flag;
1357    const unsigned char c;
1358   } flag_list[] = {
1359 <  { OPER_FLAG_ADMIN,       OPER_FLAG_HIDDEN_ADMIN,  'A' },
1360 <  { OPER_FLAG_REMOTEBAN,   0,                       'B' },
1361 <  { OPER_FLAG_DIE,         0,                       'D' },
1362 <  { OPER_FLAG_GLINE,       0,                       'G' },
1363 <  { OPER_FLAG_REHASH,      0,                       'H' },
1364 <  { OPER_FLAG_K,           0,                       'K' },
1365 <  { OPER_FLAG_OPERWALL,    0,                       'L' },
1366 <  { OPER_FLAG_N,           0,                       'N' },
1367 <  { OPER_FLAG_GLOBAL_KILL, 0,                       'O' },
1368 <  { OPER_FLAG_REMOTE,      0,                       'R' },
1369 <  { OPER_FLAG_OPER_SPY,    0,                       'S' },
1370 <  { OPER_FLAG_UNKLINE,     0,                       'U' },
1371 <  { OPER_FLAG_X,           0,                       'X' },
1372 <  { 0, 0, '\0' }
1359 >  { OPER_FLAG_ADMIN,          'A' },
1360 >  { OPER_FLAG_REMOTEBAN,      'B' },
1361 >  { OPER_FLAG_DIE,            'D' },
1362 >  { OPER_FLAG_GLINE,          'G' },
1363 >  { OPER_FLAG_REHASH,         'H' },
1364 >  { OPER_FLAG_KLINE,          'K' },
1365 >  { OPER_FLAG_KILL,           'N' },
1366 >  { OPER_FLAG_KILL_REMOTE,    'O' },
1367 >  { OPER_FLAG_CONNECT,        'P' },
1368 >  { OPER_FLAG_CONNECT_REMOTE, 'Q' },
1369 >  { OPER_FLAG_SQUIT,          'R' },
1370 >  { OPER_FLAG_SQUIT_REMOTE,   'S' },
1371 >  { OPER_FLAG_UNKLINE,        'U' },
1372 >  { OPER_FLAG_XLINE,          'X' },
1373 >  { 0, '\0' }
1374   };
1375  
1376   char *
1377   oper_privs_as_string(const unsigned int port)
1378   {
1379 <  static char privs_out[16];
1379 >  static char privs_out[IRCD_BUFSIZE];
1380    char *privs_ptr = privs_out;
2377  unsigned int i = 0;
1381  
1382 <  for (; flag_list[i].oprivs; ++i)
1382 >  for (const struct oper_privs *opriv = flag_list; opriv->flag; ++opriv)
1383    {
1384 <    if ((port & flag_list[i].oprivs) &&
1385 <        (port & flag_list[i].hidden) == 0)
2383 <      *privs_ptr++ = flag_list[i].c;
1384 >    if (port & opriv->flag)
1385 >      *privs_ptr++ = opriv->c;
1386      else
1387 <      *privs_ptr++ = ToLowerTab[flag_list[i].c];
1387 >      *privs_ptr++ = ToLower(opriv->c);
1388    }
1389  
1390    *privs_ptr = '\0';
# Line 2396 | Line 1398 | oper_privs_as_string(const unsigned int
1398   *         "oper" is server name for remote opers
1399   * Side effects: None.
1400   */
1401 < char *
1401 > const char *
1402   get_oper_name(const struct Client *client_p)
1403   {
1404 <  dlink_node *cnode;
2403 <  struct ConfItem *conf;
2404 <  struct AccessItem *aconf;
2405 <
1404 >  const dlink_node *cnode = NULL;
1405    /* +5 for !,@,{,} and null */
1406    static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
1407  
1408    if (MyConnect(client_p))
1409    {
1410 <    DLINK_FOREACH(cnode, client_p->localClient->confs.head)
1410 >    if ((cnode = client_p->localClient->confs.head))
1411      {
1412 <      conf = cnode->data;
2414 <      aconf = map_to_conf(conf);
1412 >      const struct MaskItem *conf = cnode->data;
1413  
1414 <      if (IsConfOperator(aconf))
1414 >      if (IsConfOperator(conf))
1415        {
1416 <        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1416 >        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1417                   client_p->username, client_p->host, conf->name);
1418 <        return buffer;
1418 >        return buffer;
1419        }
1420      }
1421  
1422 <    /* Probably should assert here for now. If there is an oper out there
1422 >    /* Probably should assert here for now. If there is an oper out there
1423       * with no oper{} conf attached, it would be good for us to know...
1424       */
1425      assert(0); /* Oper without oper conf! */
1426    }
1427  
1428    snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1429 <           client_p->username, client_p->host, client_p->servptr->name);
1429 >           client_p->username, client_p->host, client_p->servptr->name);
1430    return buffer;
1431   }
1432  
# Line 2441 | Line 1439 | get_oper_name(const struct Client *clien
1439   void
1440   read_conf_files(int cold)
1441   {
1442 <  const char *filename;
1443 <  char chanmodes[32];
1444 <  char chanlimit[32];
1442 >  const char *filename = NULL;
1443 >  char chanmodes[IRCD_BUFSIZE] = "";
1444 >  char chanlimit[IRCD_BUFSIZE] = "";
1445  
1446    conf_parser_ctx.boot = cold;
1447 <  filename = get_conf_name(CONF_TYPE);
1447 >  filename = ConfigFileEntry.configfile;
1448  
1449    /* We need to know the initial filename for the yyerror() to report
1450       FIXME: The full path is in conffilenamebuf first time since we
1451               dont know anything else
1452  
1453 <     - Gozem 2002-07-21
1453 >     - Gozem 2002-07-21
1454    */
1455    strlcpy(conffilebuf, filename, sizeof(conffilebuf));
1456  
1457 <  if ((conf_parser_ctx.conf_file = fbopen(filename, "r")) == NULL)
1457 >  if ((conf_parser_ctx.conf_file = fopen(filename, "r")) == NULL)
1458    {
1459      if (cold)
1460      {
1461 <      ilog(L_CRIT, "Unable to read configuration file '%s': %s",
1461 >      ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
1462             filename, strerror(errno));
1463        exit(-1);
1464      }
1465      else
1466      {
1467 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1468 <                           "Unable to read configuration file '%s': %s",
1469 <                           filename, strerror(errno));
1467 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1468 >                           "Unable to read configuration file '%s': %s",
1469 >                           filename, strerror(errno));
1470        return;
1471      }
1472    }
# Line 2477 | Line 1475 | read_conf_files(int cold)
1475      clear_out_old_conf();
1476  
1477    read_conf(conf_parser_ctx.conf_file);
1478 <  fbclose(conf_parser_ctx.conf_file);
1478 >  fclose(conf_parser_ctx.conf_file);
1479  
1480 +  log_reopen_all();
1481 +
1482 +  add_isupport("NICKLEN", NULL, ServerInfo.max_nick_length);
1483    add_isupport("NETWORK", ServerInfo.network_name, -1);
1484 <  snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
1485 <           ConfigChannel.use_except ? "e" : "",
2485 <           ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
1484 >
1485 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1486    add_isupport("MAXLIST", chanmodes, -1);
1487    add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1488 +  add_isupport("CHANTYPES", "#", -1);
1489  
1490 <  if (ConfigChannel.disable_local_channels)
1491 <    add_isupport("CHANTYPES", "#", -1);
2491 <  else
2492 <    add_isupport("CHANTYPES", "#&", -1);
2493 <
2494 <  snprintf(chanlimit, sizeof(chanlimit), "%s:%d",
2495 <           ConfigChannel.disable_local_channels ? "#" : "#&",
2496 <           ConfigChannel.max_chans_per_user);
1490 >  snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1491 >           ConfigChannel.max_channels);
1492    add_isupport("CHANLIMIT", chanlimit, -1);
1493 <  snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
1494 <           ConfigChannel.use_except ? "e" : "",
1495 <           ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
2501 <  add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2502 <
2503 <  if (ConfigChannel.use_except)
2504 <    add_isupport("EXCEPTS", "e", -1);
2505 <  if (ConfigChannel.use_invex)
2506 <    add_isupport("INVEX", "I", -1);
1493 >  snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,imnprstORS");
1494 >  add_isupport("CHANNELLEN", NULL, CHANNELLEN);
1495 >  add_isupport("TOPICLEN", NULL, ServerInfo.max_topic_length);
1496    add_isupport("CHANMODES", chanmodes, -1);
1497  
1498    /*
# Line 2511 | Line 1500 | read_conf_files(int cold)
1500     * on strlen(form_str(RPL_ISUPPORT))
1501     */
1502    rebuild_isupport_message_line();
2514
2515 #ifdef HAVE_LIBPCRE
2516  parse_conf_file(RKLINE_TYPE, cold);
2517  parse_conf_file(RXLINE_TYPE, cold);
2518 #endif
2519  parse_conf_file(KLINE_TYPE, cold);
2520  parse_conf_file(DLINE_TYPE, cold);
2521  parse_conf_file(XLINE_TYPE, cold);
2522  parse_conf_file(NRESV_TYPE, cold);
2523  parse_conf_file(CRESV_TYPE, cold);
2524 }
2525
2526 /* parse_conf_file()
2527 *
2528 * inputs       - type of conf file to parse
2529 * output       - none
2530 * side effects - conf file for givenconf type is opened and read then parsed
2531 */
2532 static void
2533 parse_conf_file(int type, int cold)
2534 {
2535  FBFILE *file = NULL;
2536  const char *filename = get_conf_name(type);
2537
2538  if ((file = fbopen(filename, "r")) == NULL)
2539  {
2540    if (cold)
2541      ilog(L_ERROR, "Unable to read configuration file '%s': %s",
2542           filename, strerror(errno));
2543    else
2544      sendto_realops_flags(UMODE_ALL, L_ALL,
2545                    "Unable to read configuration file '%s': %s",
2546                           filename, strerror(errno));
2547  }
2548  else
2549  {
2550    parse_csv_file(file, type);
2551    fbclose(file);
2552  }
1503   }
1504  
1505   /* clear_out_old_conf()
# Line 2562 | Line 1512 | static void
1512   clear_out_old_conf(void)
1513   {
1514    dlink_node *ptr = NULL, *next_ptr = NULL;
1515 <  struct ConfItem *conf;
2566 <  struct AccessItem *aconf;
2567 <  struct ClassItem *cltmp;
2568 <  struct MatchItem *match_item;
1515 >  struct MaskItem *conf;
1516    dlink_list *free_items [] = {
1517 <    &server_items,   &oconf_items,    &hub_items, &leaf_items,
1518 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1519 <     &nresv_items, &cluster_items,  &gdeny_items, &service_items, NULL
1517 >    &server_items,   &oconf_items,
1518 >     &uconf_items,   &xconf_items,
1519 >     &nresv_items, &cluster_items,  &service_items, &cresv_items, NULL
1520    };
1521  
1522    dlink_list ** iterator = free_items; /* C is dumb */
# Line 2577 | Line 1524 | clear_out_old_conf(void)
1524    /* We only need to free anything allocated by yyparse() here.
1525     * Resetting structs, etc, is taken care of by set_default_conf().
1526     */
1527 <  
1527 >
1528    for (; *iterator != NULL; iterator++)
1529    {
1530      DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1531      {
1532        conf = ptr->data;
2586      /* XXX This is less than pretty */
2587      if (conf->type == SERVER_TYPE)
2588      {
2589        aconf = map_to_conf(conf);
1533  
1534 <        if (aconf->clients != 0)
2592 <        {
2593 <          SetConfIllegal(aconf);
2594 <          dlinkDelete(&conf->node, &server_items);
2595 <        }
2596 <        else
2597 <        {
2598 <          delete_conf_item(conf);
2599 <        }
2600 <      }
2601 <      else if (conf->type == OPER_TYPE)
2602 <      {
2603 <        aconf = map_to_conf(conf);
1534 >      dlinkDelete(&conf->node, map_to_list(conf->type));
1535  
1536 <        if (aconf->clients != 0)
1537 <        {
2607 <          SetConfIllegal(aconf);
2608 <          dlinkDelete(&conf->node, &oconf_items);
2609 <        }
2610 <        else
2611 <        {
2612 <          delete_conf_item(conf);
2613 <        }
2614 <      }
2615 <      else if (conf->type == CLIENT_TYPE)
1536 >      /* XXX This is less than pretty */
1537 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1538        {
1539 <        aconf = map_to_conf(conf);
1540 <
2619 <        if (aconf->clients != 0)
2620 <        {
2621 <          SetConfIllegal(aconf);
2622 <        }
2623 <        else
2624 <        {
2625 <          delete_conf_item(conf);
2626 <        }
1539 >        if (!conf->ref_count)
1540 >          conf_free(conf);
1541        }
1542 <      else if (conf->type == XLINE_TYPE  ||
2629 <               conf->type == RXLINE_TYPE ||
2630 <               conf->type == RKLINE_TYPE)
1542 >      else if (conf->type == CONF_XLINE)
1543        {
1544 <        /* temporary (r)xlines are also on
1545 <         * the (r)xconf items list */
2634 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2635 <          continue;
2636 <
2637 <        delete_conf_item(conf);
1544 >        if (!conf->until)
1545 >          conf_free(conf);
1546        }
1547        else
1548 <      {
2641 <        if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2642 <        {
2643 <          match_item = map_to_conf(conf);
2644 <          if (match_item->ref_count <= 0)
2645 <            delete_conf_item(conf);
2646 <          else
2647 <          {
2648 <            match_item->illegal = 1;
2649 <            dlinkDelete(&conf->node, *iterator);
2650 <          }
2651 <        }
2652 <        else
2653 <          delete_conf_item(conf);
2654 <      }
1548 >        conf_free(conf);
1549      }
1550    }
1551  
1552 +  motd_clear();
1553 +
1554    /*
1555     * don't delete the class table, rather mark all entries
1556 <   * for deletion. The table is cleaned up by check_class. - avalon
1556 >   * for deletion. The table is cleaned up by class_delete_marked. - avalon
1557     */
1558 <  DLINK_FOREACH(ptr, class_items.head)
2663 <  {
2664 <    cltmp = map_to_conf(ptr->data);
2665 <
2666 <    if (ptr != class_items.tail)  /* never mark the "default" class */
2667 <      cltmp->active = 0;
2668 <  }
1558 >  class_mark_for_deletion();
1559  
1560    clear_out_address_conf();
1561  
# Line 2682 | Line 1572 | clear_out_old_conf(void)
1572    MyFree(ConfigFileEntry.egdpool_path);
1573    ConfigFileEntry.egdpool_path = NULL;
1574   #ifdef HAVE_LIBCRYPTO
1575 <  if (ServerInfo.rsa_private_key != NULL)
1575 >  if (ServerInfo.rsa_private_key)
1576    {
1577      RSA_free(ServerInfo.rsa_private_key);
1578      ServerInfo.rsa_private_key = NULL;
# Line 2690 | Line 1580 | clear_out_old_conf(void)
1580  
1581    MyFree(ServerInfo.rsa_private_key_file);
1582    ServerInfo.rsa_private_key_file = NULL;
2693 #endif
1583  
1584 <  /* clean out old resvs from the conf */
1585 <  clear_conf_resv();
1584 >  if (ServerInfo.server_ctx)
1585 >    SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
1586 >                                               SSL_OP_NO_SSLv3|
1587 >                                               SSL_OP_NO_TLSv1);
1588 >  if (ServerInfo.client_ctx)
1589 >    SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
1590 >                                               SSL_OP_NO_SSLv3|
1591 >                                               SSL_OP_NO_TLSv1);
1592 > #endif
1593  
1594    /* clean out AdminInfo */
1595    MyFree(AdminInfo.name);
# Line 2703 | Line 1599 | clear_out_old_conf(void)
1599    MyFree(AdminInfo.description);
1600    AdminInfo.description = NULL;
1601  
2706  /* operator{} and class{} blocks are freed above */
1602    /* clean out listeners */
1603    close_listeners();
1604  
2710  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2711   * exempt{} and gecos{} blocks are freed above too
2712   */
2713
1605    /* clean out general */
1606    MyFree(ConfigFileEntry.service_name);
1607    ConfigFileEntry.service_name = NULL;
2717
2718  MyFree(ConfigFileEntry.servlink_path);
2719  ConfigFileEntry.servlink_path = NULL;
2720 #ifdef HAVE_LIBCRYPTO
2721  ConfigFileEntry.default_cipher_preference = NULL;
2722 #endif /* HAVE_LIBCRYPTO */
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, 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;
1608   }
1609  
1610   /* conf_add_class_to_conf()
1611   *
1612   * inputs       - pointer to config item
1613   * output       - NONE
1614 < * side effects - Add a class pointer to a conf
1614 > * side effects - Add a class pointer to a conf
1615   */
1616   void
1617 < conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
1617 > conf_add_class_to_conf(struct MaskItem *conf, const char *class_name)
1618   {
1619 <  struct AccessItem *aconf = map_to_conf(conf);
3020 <  struct ClassItem *class = NULL;
3021 <
3022 <  if (class_name == NULL)
1619 >  if (class_name == NULL)
1620    {
1621 <    aconf->class_ptr = class_default;
1621 >    conf->class = class_default;
1622  
1623 <    if (conf->type == CLIENT_TYPE)
1624 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1625 <                           "Warning *** Defaulting to default class for %s@%s",
1626 <                           aconf->user, aconf->host);
1623 >    if (conf->type == CONF_CLIENT)
1624 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1625 >                           "Warning *** Defaulting to default class for %s@%s",
1626 >                           conf->user, conf->host);
1627      else
1628 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1629 <                           "Warning *** Defaulting to default class for %s",
1630 <                           conf->name);
1628 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1629 >                           "Warning *** Defaulting to default class for %s",
1630 >                           conf->name);
1631    }
1632    else
1633 <    aconf->class_ptr = find_class(class_name);
3037 <
3038 <  if (aconf->class_ptr)
3039 <    class = map_to_conf(aconf->class_ptr);
1633 >    conf->class = class_find(class_name, 1);
1634  
1635 <  if (aconf->class_ptr == NULL || !class->active)
1635 >  if (conf->class == NULL)
1636    {
1637 <    if (conf->type == CLIENT_TYPE)
1638 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1639 <                           "Warning *** Defaulting to default class for %s@%s",
1640 <                           aconf->user, aconf->host);
1637 >    if (conf->type == CONF_CLIENT)
1638 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1639 >                           "Warning *** Defaulting to default class for %s@%s",
1640 >                           conf->user, conf->host);
1641      else
1642 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1643 <                           "Warning *** Defaulting to default class for %s",
1644 <                           conf->name);
1645 <    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(L_WARN, "Bad connect block");
3078 <    return -1;
1642 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1643 >                           "Warning *** Defaulting to default class for %s",
1644 >                           conf->name);
1645 >    conf->class = class_default;
1646    }
3080
3081  if (EmptyString(aconf->passwd) && !IsConfCryptLink(aconf))
3082  {
3083    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
3084                         conf->name);
3085    ilog(L_WARN, "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;
1647   }
1648  
1649   /* yyerror()
# Line 3124 | Line 1661 | yyerror(const char *msg)
1661      return;
1662  
1663    strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1664 <  sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
1664 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1665 >                       "\"%s\", line %u: %s: %s",
1666                         conffilebuf, lineno + 1, msg, newlinebuf);
1667 <  ilog(L_WARN, "\"%s\", line %u: %s: %s",
1667 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1668         conffilebuf, lineno + 1, msg, newlinebuf);
1669   }
1670  
1671 < int
1672 < conf_fbgets(char *lbuf, unsigned int max_size, FBFILE *fb)
1671 > void
1672 > conf_error_report(const char *msg)
1673   {
1674 <  if (fbgets(lbuf, max_size, fb) == NULL)
3137 <    return 0;
3138 <
3139 <  return strlen(lbuf);
3140 < }
1674 >  char newlinebuf[IRCD_BUFSIZE];
1675  
1676 < int
1677 < conf_yy_fatal_error(const char *msg)
1678 < {
1679 <  return 0;
1676 >  strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1677 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1678 >                       "\"%s\", line %u: %s: %s",
1679 >                       conffilebuf, lineno + 1, msg, newlinebuf);
1680 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1681 >       conffilebuf, lineno + 1, msg, newlinebuf);
1682   }
1683  
1684   /*
1685   * valid_tkline()
1686 < *
1686 > *
1687   * inputs       - pointer to ascii string to check
1688   *              - whether the specified time is in seconds or minutes
1689   * output       - -1 not enough parameters
# Line 3156 | Line 1692 | conf_yy_fatal_error(const char *msg)
1692   * Originally written by Dianora (Diane, db@db.net)
1693   */
1694   time_t
1695 < valid_tkline(const char *p, int minutes)
1695 > valid_tkline(const char *data, const int minutes)
1696   {
1697 +  const unsigned char *p = (const unsigned char *)data;
1698 +  unsigned char tmpch = '\0';
1699    time_t result = 0;
1700  
1701 <  for (; *p; ++p)
1701 >  while ((tmpch = *p++))
1702    {
1703 <    if (!IsDigit(*p))
1703 >    if (!IsDigit(tmpch))
1704        return 0;
1705  
1706      result *= 10;
1707 <    result += ((*p) & 0xF);
1707 >    result += (tmpch & 0xF);
1708    }
1709  
1710    /*
1711 <   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1711 >   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1712     * i.e. they specifically use 0, I am going to return 1 instead
1713     * as a return value of non-zero is used to flag it as a temporary kline
1714     */
1715    if (result == 0)
1716      result = 1;
1717  
1718 <  /*
1718 >  /*
1719     * If the incoming time is in seconds convert it to minutes for the purpose
1720     * of this calculation
1721     */
1722    if (!minutes)
1723 <    result = result / (time_t)60;
1723 >    result = result / 60;
1724  
1725    if (result > MAX_TDKLINE_TIME)
1726      result = MAX_TDKLINE_TIME;
1727  
1728 <  result = result * (time_t)60;  /* turn it into seconds */
1728 >  result = result * 60;  /* turn it into seconds */
1729  
1730    return result;
1731   }
1732  
1733 + /* valid_wild_card_simple()
1734 + *
1735 + * inputs       - data to check for sufficient non-wildcard characters
1736 + * outputs      - 1 if valid, else 0
1737 + * side effects - none
1738 + */
1739 + int
1740 + valid_wild_card_simple(const char *data)
1741 + {
1742 +  const unsigned char *p = (const unsigned char *)data;
1743 +  unsigned char tmpch = '\0';
1744 +  unsigned int nonwild = 0;
1745 +
1746 +  while ((tmpch = *p++))
1747 +  {
1748 +    if (tmpch == '\\')
1749 +    {
1750 +      ++p;
1751 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1752 +        return 1;
1753 +    }
1754 +    else if (!IsMWildChar(tmpch))
1755 +    {
1756 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1757 +        return 1;
1758 +    }
1759 +  }
1760 +
1761 +  return 0;
1762 + }
1763 +
1764   /* valid_wild_card()
1765   *
1766   * input        - pointer to client
# Line 3203 | Line 1772 | valid_tkline(const char *p, int minutes)
1772   int
1773   valid_wild_card(struct Client *source_p, int warn, int count, ...)
1774   {
1775 <  char *p;
1776 <  char tmpch;
3208 <  int nonwild = 0;
1775 >  unsigned char tmpch = '\0';
1776 >  unsigned int nonwild = 0;
1777    va_list args;
1778  
1779    /*
# Line 3224 | Line 1792 | valid_wild_card(struct Client *source_p,
1792  
1793    while (count--)
1794    {
1795 <    p = va_arg(args, char *);
1795 >    const unsigned char *p = va_arg(args, const unsigned char *);
1796      if (p == NULL)
1797        continue;
1798  
# Line 3237 | Line 1805 | valid_wild_card(struct Client *source_p,
1805           * break - no point in searching further.
1806           */
1807          if (++nonwild >= ConfigFileEntry.min_nonwildcard)
1808 +        {
1809 +          va_end(args);
1810            return 1;
1811 +        }
1812        }
1813      }
1814    }
1815  
1816    if (warn)
1817 <    sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
1818 <               me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
1817 >    sendto_one_notice(source_p, &me,
1818 >                      ":Please include at least %d non-wildcard characters with the mask",
1819 >                      ConfigFileEntry.min_nonwildcard);
1820 >  va_end(args);
1821    return 0;
1822   }
1823  
# Line 3258 | Line 1831 | valid_wild_card(struct Client *source_p,
1831   *              - parse_flags bit map of things to test
1832   *              - pointer to user or string to parse into
1833   *              - pointer to host or NULL to parse into if non NULL
1834 < *              - pointer to optional tkline time or NULL
1834 > *              - pointer to optional tkline time or NULL
1835   *              - pointer to target_server to parse into if non NULL
1836   *              - pointer to reason to parse into
1837   *
# Line 3280 | Line 1853 | valid_wild_card(struct Client *source_p,
1853   */
1854   int
1855   parse_aline(const char *cmd, struct Client *source_p,
1856 <            int parc, char **parv,
1857 <            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1858 <            char **target_server, char **reason)
1856 >            int parc, char **parv,
1857 >            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1858 >            char **target_server, char **reason)
1859   {
1860    int found_tkline_time=0;
1861 <  static char def_reason[] = "No Reason";
1861 >  static char def_reason[] = CONF_NOREASON;
1862    static char user[USERLEN*4+1];
1863    static char host[HOSTLEN*4+1];
1864  
# Line 3303 | Line 1876 | parse_aline(const char *cmd, struct Clie
1876        *tkline_time = found_tkline_time;
1877      else
1878      {
1879 <      sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3307 <                 me.name, source_p->name, cmd);
1879 >      sendto_one_notice(source_p, &me, ":temp_line not supported by %s", cmd);
1880        return -1;
1881      }
1882    }
1883  
1884    if (parc == 0)
1885    {
1886 <    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3315 <               me.name, source_p->name, cmd);
1886 >    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1887      return -1;
1888    }
1889  
# Line 3326 | Line 1897 | parse_aline(const char *cmd, struct Clie
1897      *up_p = user;
1898      *h_p = host;
1899    }
1900 <
1900 >
1901    parc--;
1902    parv++;
1903  
# Line 3339 | Line 1910 | parse_aline(const char *cmd, struct Clie
1910  
1911        if (target_server == NULL)
1912        {
1913 <        sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
1914 <                   me.name, source_p->name, cmd);
3344 <        return -1;
1913 >        sendto_one_notice(source_p, &me, ":ON server not supported by %s", cmd);
1914 >        return -1;
1915        }
1916  
1917 <      if (!IsOperRemoteBan(source_p))
1917 >      if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
1918        {
1919 <        sendto_one(source_p, form_str(ERR_NOPRIVS),
3350 <                   me.name, source_p->name, "remoteban");
1919 >        sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "remoteban");
1920          return -1;
1921        }
1922  
1923        if (parc == 0 || EmptyString(*parv))
1924        {
1925 <        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1926 <                   me.name, source_p->name, cmd);
3358 <        return -1;
1925 >        sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1926 >        return -1;
1927        }
1928  
1929        *target_server = *parv;
# Line 3368 | Line 1936 | parse_aline(const char *cmd, struct Clie
1936         * caller probably NULL'd it first, but no harm to do it again -db
1937         */
1938        if (target_server != NULL)
1939 <        *target_server = NULL;
1939 >        *target_server = NULL;
1940      }
1941    }
1942  
# Line 3376 | Line 1944 | parse_aline(const char *cmd, struct Clie
1944    {
1945      if (strchr(user, '!') != NULL)
1946      {
1947 <      sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3380 <                 me.name, source_p->name);
1947 >      sendto_one_notice(source_p, &me, ":Invalid character '!' in kline");
1948        return -1;
1949      }
1950  
1951 <    if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 2, *up_p, *h_p))
1951 >    if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 2, *up_p, *h_p))
1952        return -1;
1953    }
1954    else
1955 <    if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 1, *up_p))
1955 >    if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 1, *up_p))
1956        return -1;
1957  
1958    if (reason != NULL)
# Line 3393 | Line 1960 | parse_aline(const char *cmd, struct Clie
1960      if (parc != 0 && !EmptyString(*parv))
1961      {
1962        *reason = *parv;
1963 <      if (!valid_comment(source_p, *reason, YES))
1964 <        return -1;
1963 >      if (!valid_comment(source_p, *reason, 1))
1964 >        return -1;
1965      }
1966      else
1967        *reason = def_reason;
# Line 3433 | Line 2000 | find_user_host(struct Client *source_p,
2000      {
2001        *(hostp++) = '\0';                       /* short and squat */
2002        if (*user_host_or_nick)
2003 <        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
2003 >        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
2004        else
2005 <        strcpy(luser, "*");
2005 >        strcpy(luser, "*");
2006 >
2007        if (*hostp)
2008 <        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
2008 >        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
2009        else
2010 <        strcpy(lhost, "*");
2010 >        strcpy(lhost, "*");
2011      }
2012      else
2013      {
2014        luser[0] = '*';             /* no @ found, assume its *@somehost */
2015 <      luser[1] = '\0';    
2015 >      luser[1] = '\0';
2016        strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
2017      }
2018 <    
2018 >
2019      return 1;
2020    }
2021 <  else if (!(flags & NOUSERLOOKUP))
2021 >  else
2022    {
2023      /* Try to find user@host mask from nick */
2024      /* Okay to use source_p as the first param, because source_p == client_p */
2025 <    if ((target_p =
2026 <        find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
2027 <      return 0;
2025 >    if ((target_p =
2026 >        find_chasing(source_p, user_host_or_nick)) == NULL)
2027 >      return 0;  /* find_chasing sends ERR_NOSUCHNICK */
2028  
2029      if (IsExemptKline(target_p))
2030      {
2031        if (!IsServer(source_p))
2032 <        sendto_one(source_p,
3465 <                   ":%s NOTICE %s :%s is E-lined",
3466 <                   me.name, source_p->name, target_p->name);
2032 >        sendto_one_notice(source_p, &me, ":%s is E-lined", target_p->name);
2033        return 0;
2034      }
2035  
# Line 3498 | Line 2064 | find_user_host(struct Client *source_p,
2064   int
2065   valid_comment(struct Client *source_p, char *comment, int warn)
2066   {
3501  if (strchr(comment, '"'))
3502  {
3503    if (warn)
3504      sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3505                 me.name, source_p->name);
3506    return 0;
3507  }
3508
2067    if (strlen(comment) > REASONLEN)
2068      comment[REASONLEN-1] = '\0';
2069  
# Line 3520 | Line 2078 | valid_comment(struct Client *source_p, c
2078   * side effects - none
2079   */
2080   int
2081 < match_conf_password(const char *password, const struct AccessItem *aconf)
2081 > match_conf_password(const char *password, const struct MaskItem *conf)
2082   {
2083    const char *encr = NULL;
2084  
2085 <  if (password == NULL || aconf->passwd == NULL)
2085 >  if (EmptyString(password) || EmptyString(conf->passwd))
2086      return 0;
2087  
2088 <  if (aconf->flags & CONF_FLAGS_ENCRYPTED)
2089 <  {
3532 <    /* use first two chars of the password they send in as salt */
3533 <    /* If the password in the conf is MD5, and ircd is linked
3534 <     * to scrypt on FreeBSD, or the standard crypt library on
3535 <     * glibc Linux, then this code will work fine on generating
3536 <     * the proper encrypted hash for comparison.
3537 <     */
3538 <    if (*aconf->passwd)
3539 <      encr = crypt(password, aconf->passwd);
3540 <    else
3541 <      encr = "";
3542 <  }
2088 >  if (conf->flags & CONF_FLAGS_ENCRYPTED)
2089 >    encr = crypt(password, conf->passwd);
2090    else
2091      encr = password;
2092  
2093 <  return !strcmp(encr, aconf->passwd);
2093 >  return encr && !strcmp(encr, conf->passwd);
2094   }
2095  
2096   /*
# Line 3551 | Line 2098 | match_conf_password(const char *password
2098   *
2099   * inputs       - client sending the cluster
2100   *              - command name "KLINE" "XLINE" etc.
2101 < *              - capab -- CAP_KLN etc. from s_serv.h
2102 < *              - cluster type -- CLUSTER_KLINE etc. from s_conf.h
2101 > *              - capab -- CAP_KLN etc. from server.h
2102 > *              - cluster type -- CLUSTER_KLINE etc. from conf.h
2103   *              - pattern and args to send along
2104   * output       - none
2105   * side effects - Take source_p send the pattern with args given
# Line 3563 | Line 2110 | cluster_a_line(struct Client *source_p,
2110                 int capab, int cluster_type, const char *pattern, ...)
2111   {
2112    va_list args;
2113 <  char buffer[IRCD_BUFSIZE];
2113 >  char buffer[IRCD_BUFSIZE] = "";
2114    const dlink_node *ptr = NULL;
2115  
2116    va_start(args, pattern);
# Line 3572 | Line 2119 | cluster_a_line(struct Client *source_p,
2119  
2120    DLINK_FOREACH(ptr, cluster_items.head)
2121    {
2122 <    const struct ConfItem *conf = ptr->data;
2122 >    const struct MaskItem *conf = ptr->data;
2123  
2124      if (conf->flags & cluster_type)
2125        sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
2126 <                         "%s %s %s", command, conf->name, buffer);
2126 >                         "%s %s %s", command, conf->name, buffer);
2127    }
2128   }
2129  
# Line 3624 | Line 2171 | split_nuh(struct split_nuh_item *const i
2171    {
2172      *p = '\0';
2173  
2174 <    if (iptr->nickptr && *iptr->nuhmask != '\0')
2174 >    if (iptr->nickptr && *iptr->nuhmask)
2175        strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
2176  
2177 <    if ((q = strchr(++p, '@'))) {
2177 >    if ((q = strchr(++p, '@')))
2178 >    {
2179        *q++ = '\0';
2180  
2181 <      if (*p != '\0')
2181 >      if (*p)
2182          strlcpy(iptr->userptr, p, iptr->usersize);
2183  
2184 <      if (*q != '\0')
2184 >      if (*q)
2185          strlcpy(iptr->hostptr, q, iptr->hostsize);
2186      }
2187      else
2188      {
2189 <      if (*p != '\0')
2189 >      if (*p)
2190          strlcpy(iptr->userptr, p, iptr->usersize);
2191      }
2192    }
# Line 3650 | Line 2198 | split_nuh(struct split_nuh_item *const i
2198        /* if found a @ */
2199        *p++ = '\0';
2200  
2201 <      if (*iptr->nuhmask != '\0')
2201 >      if (*iptr->nuhmask)
2202          strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
2203  
2204 <      if (*p != '\0')
2204 >      if (*p)
2205          strlcpy(iptr->hostptr, p, iptr->hostsize);
2206      }
2207      else
# Line 3666 | Line 2214 | split_nuh(struct split_nuh_item *const i
2214      }
2215    }
2216   }
3669
3670 /*
3671 * flags_to_ascii
3672 *
3673 * inputs       - flags is a bitmask
3674 *              - pointer to table of ascii letters corresponding
3675 *                to each bit
3676 *              - flag 1 for convert ToLower if bit missing
3677 *                0 if ignore.
3678 * output       - none
3679 * side effects - string pointed to by p has bitmap chars written to it
3680 */
3681 static void
3682 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3683               int lowerit)
3684 {
3685  unsigned int mask = 1;
3686  int i = 0;
3687
3688  for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3689  {
3690    if (flags & mask)
3691      *p++ = bit_table[i];
3692    else if (lowerit)
3693      *p++ = ToLower(bit_table[i]);
3694  }
3695  *p = '\0';
3696 }
3697
3698 /*
3699 * cidr_limit_reached
3700 *
3701 * inputs       - int flag allowing over_rule of limits
3702 *              - pointer to the ip to be added
3703 *              - pointer to the class
3704 * output       - non zero if limit reached
3705 *                0 if limit not reached
3706 * side effects -
3707 */
3708 static int
3709 cidr_limit_reached(int over_rule,
3710                   struct irc_ssaddr *ip, struct ClassItem *aclass)
3711 {
3712  dlink_node *ptr = NULL;
3713  struct CidrItem *cidr;
3714
3715  if (NumberPerCidr(aclass) <= 0)
3716    return 0;
3717
3718  if (ip->ss.ss_family == AF_INET)
3719  {
3720    if (CidrBitlenIPV4(aclass) <= 0)
3721      return 0;
3722
3723    DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3724    {
3725      cidr = ptr->data;
3726      if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3727      {
3728        if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3729          return -1;
3730        cidr->number_on_this_cidr++;
3731        return 0;
3732      }
3733    }
3734    cidr = MyMalloc(sizeof(struct CidrItem));
3735    cidr->number_on_this_cidr = 1;
3736    cidr->mask = *ip;
3737    mask_addr(&cidr->mask, CidrBitlenIPV4(aclass));
3738    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3739  }
3740 #ifdef IPV6
3741  else if (CidrBitlenIPV6(aclass) > 0)
3742  {
3743    DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3744    {
3745      cidr = ptr->data;
3746      if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3747      {
3748        if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3749          return -1;
3750        cidr->number_on_this_cidr++;
3751        return 0;
3752      }
3753    }
3754    cidr = MyMalloc(sizeof(struct CidrItem));
3755    cidr->number_on_this_cidr = 1;
3756    cidr->mask = *ip;
3757    mask_addr(&cidr->mask, CidrBitlenIPV6(aclass));
3758    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3759  }
3760 #endif
3761  return 0;
3762 }
3763
3764 /*
3765 * remove_from_cidr_check
3766 *
3767 * inputs       - pointer to the ip to be removed
3768 *              - pointer to the class
3769 * output       - NONE
3770 * side effects -
3771 */
3772 static void
3773 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3774 {
3775  dlink_node *ptr = NULL;
3776  dlink_node *next_ptr = NULL;
3777  struct CidrItem *cidr;
3778
3779  if (NumberPerCidr(aclass) == 0)
3780    return;
3781
3782  if (ip->ss.ss_family == AF_INET)
3783  {
3784    if (CidrBitlenIPV4(aclass) <= 0)
3785      return;
3786
3787    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3788    {
3789      cidr = ptr->data;
3790      if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3791      {
3792        cidr->number_on_this_cidr--;
3793        if (cidr->number_on_this_cidr == 0)
3794        {
3795          dlinkDelete(ptr, &aclass->list_ipv4);
3796          MyFree(cidr);
3797          return;
3798        }
3799      }
3800    }
3801  }
3802 #ifdef IPV6
3803  else if (CidrBitlenIPV6(aclass) > 0)
3804  {
3805    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3806    {
3807      cidr = ptr->data;
3808      if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3809      {
3810        cidr->number_on_this_cidr--;
3811        if (cidr->number_on_this_cidr == 0)
3812        {
3813          dlinkDelete(ptr, &aclass->list_ipv6);
3814          MyFree(cidr);
3815          return;
3816        }
3817      }
3818    }
3819  }
3820 #endif
3821 }
3822
3823 static void
3824 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3825                  dlink_list *old_list, dlink_list *new_list, int changed)
3826 {
3827  dlink_node *ptr;
3828  struct Client *client_p;
3829  struct ConfItem *conf;
3830  struct AccessItem *aconf;
3831
3832  if (!changed)
3833  {
3834    *new_list = *old_list;
3835    old_list->head = old_list->tail = NULL;
3836    old_list->length = 0;
3837    return;
3838  }
3839
3840  DLINK_FOREACH(ptr, local_client_list.head)
3841  {
3842    client_p = ptr->data;
3843    if (client_p->localClient->aftype != aftype)
3844      continue;
3845    if (dlink_list_length(&client_p->localClient->confs) == 0)
3846      continue;
3847
3848    conf = client_p->localClient->confs.tail->data;
3849    if (conf->type == CLIENT_TYPE)
3850    {
3851      aconf = map_to_conf(conf);
3852      if (aconf->class_ptr == oldcl)
3853        cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3854    }
3855  }
3856 }
3857
3858 /*
3859 * rebuild_cidr_class
3860 *
3861 * inputs       - pointer to old conf
3862 *              - pointer to new_class
3863 * output       - none
3864 * side effects - rebuilds the class link list of cidr blocks
3865 */
3866 void
3867 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3868 {
3869  struct ClassItem *old_class = map_to_conf(conf);
3870
3871  if (NumberPerCidr(old_class) > 0 && NumberPerCidr(new_class) > 0)
3872  {
3873    if (CidrBitlenIPV4(old_class) > 0 && CidrBitlenIPV4(new_class) > 0)
3874      rebuild_cidr_list(AF_INET, conf, new_class,
3875                        &old_class->list_ipv4, &new_class->list_ipv4,
3876                        CidrBitlenIPV4(old_class) != CidrBitlenIPV4(new_class));
3877
3878 #ifdef IPV6
3879    if (CidrBitlenIPV6(old_class) > 0 && CidrBitlenIPV6(new_class) > 0)
3880      rebuild_cidr_list(AF_INET6, conf, new_class,
3881                        &old_class->list_ipv6, &new_class->list_ipv6,
3882                        CidrBitlenIPV6(old_class) != CidrBitlenIPV6(new_class));
3883 #endif
3884  }
3885
3886  destroy_cidr_class(old_class);
3887 }
3888
3889 /*
3890 * destroy_cidr_list
3891 *
3892 * inputs       - pointer to class dlink list of cidr blocks
3893 * output       - none
3894 * side effects - completely destroys the class link list of cidr blocks
3895 */
3896 static void
3897 destroy_cidr_list(dlink_list *list)
3898 {
3899  dlink_node *ptr = NULL, *next_ptr = NULL;
3900
3901  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3902  {
3903    dlinkDelete(ptr, list);
3904    MyFree(ptr->data);
3905  }
3906 }
3907
3908 /*
3909 * destroy_cidr_class
3910 *
3911 * inputs       - pointer to class
3912 * output       - none
3913 * side effects - completely destroys the class link list of cidr blocks
3914 */
3915 static void
3916 destroy_cidr_class(struct ClassItem *aclass)
3917 {
3918  destroy_cidr_list(&aclass->list_ipv4);
3919  destroy_cidr_list(&aclass->list_ipv6);
3920 }

Diff Legend

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