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

Comparing:
ircd-hybrid-8/src/conf.c (file contents), Revision 1389 by michael, Tue May 1 13:08:29 2012 UTC vs.
ircd-hybrid/trunk/src/conf.c (file contents), Revision 4744 by michael, Thu Oct 16 11:46:19 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  conf.c: Configuration file functions.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 16 | Line 15
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18 < *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file conf.c
23 > * \brief Configuration file functions.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28   #include "list.h"
29   #include "ircd_defs.h"
28 #include "balloc.h"
30   #include "conf.h"
31 < #include "s_serv.h"
31 > #include "conf_pseudo.h"
32 > #include "server.h"
33   #include "resv.h"
34   #include "channel.h"
35   #include "client.h"
36   #include "event.h"
35 #include "hook.h"
37   #include "irc_string.h"
38   #include "s_bsd.h"
39   #include "ircd.h"
# Line 43 | Line 44
44   #include "fdlist.h"
45   #include "log.h"
46   #include "send.h"
46 #include "s_gline.h"
47   #include "memory.h"
48 < #include "irc_res.h"
48 > #include "res.h"
49   #include "userhost.h"
50 < #include "s_user.h"
50 > #include "user.h"
51   #include "channel_mode.h"
52   #include "parse.h"
53 < #include "s_misc.h"
53 > #include "misc.h"
54 > #include "conf_db.h"
55 > #include "conf_class.h"
56 > #include "motd.h"
57 > #include "ipcache.h"
58  
55 struct Callback *client_check_cb = NULL;
56 struct config_server_hide ConfigServerHide;
59  
60   /* general conf items link list root, other than k lines etc. */
61   dlink_list service_items = { NULL, NULL, 0 };
# Line 62 | Line 64 | dlink_list cluster_items = { NULL, NULL,
64   dlink_list oconf_items   = { NULL, NULL, 0 };
65   dlink_list uconf_items   = { NULL, NULL, 0 };
66   dlink_list xconf_items   = { NULL, NULL, 0 };
65 dlink_list rxconf_items  = { NULL, NULL, 0 };
66 dlink_list rkconf_items  = { NULL, NULL, 0 };
67   dlink_list nresv_items   = { NULL, NULL, 0 };
68 < dlink_list class_items   = { NULL, NULL, 0 };
69 < dlink_list gdeny_items   = { NULL, NULL, 0 };
70 <
71 < dlink_list temporary_xlines  = { NULL, NULL, 0 };
72 < dlink_list temporary_resv = { NULL, NULL, 0 };
68 > dlink_list cresv_items   = { NULL, NULL, 0 };
69  
70   extern unsigned int lineno;
71   extern char linebuf[];
72   extern char conffilebuf[IRCD_BUFSIZE];
73   extern int yyparse(); /* defined in y.tab.c */
74  
79 struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
80
75   /* internally defined functions */
76   static void read_conf(FILE *);
77   static void clear_out_old_conf(void);
84 static void flush_deleted_I_P(void);
78   static void expire_tklines(dlink_list *);
79 < static void garbage_collect_ip_entries(void);
80 < static int hash_ip(struct irc_ssaddr *);
81 < static int verify_access(struct Client *, const char *);
89 < static int attach_iline(struct Client *, struct ConfItem *);
90 < static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
91 < static void parse_conf_file(int, int);
92 < static dlink_list *map_to_list(ConfType);
93 < static struct AccessItem *find_regexp_kline(const char *[]);
79 > static int verify_access(struct Client *);
80 > static int attach_iline(struct Client *, struct MaskItem *);
81 > static dlink_list *map_to_list(enum maskitem_type);
82   static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
83  
96 /*
97 * bit_len
98 */
99 static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
100 static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
101 static void destroy_cidr_class(struct ClassItem *);
102
103 static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
104
105 /* address of default class conf */
106 static struct ConfItem *class_default;
107
108 /* usually, with hash tables, you use a prime number...
109 * but in this case I am dealing with ip addresses,
110 * not ascii strings.
111 */
112 #define IP_HASH_SIZE 0x1000
113
114 struct ip_entry
115 {
116  struct irc_ssaddr ip;
117  int count;
118  time_t last_attempt;
119  struct ip_entry *next;
120 };
121
122 static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
123 static BlockHeap *ip_entry_heap = NULL;
124 static int ip_entries_count = 0;
125
126
127 void *
128 map_to_conf(struct ConfItem *aconf)
129 {
130  void *conf;
131  conf = (void *)((uintptr_t)aconf +
132                  (uintptr_t)sizeof(struct ConfItem));
133  return(conf);
134 }
135
136 struct ConfItem *
137 unmap_conf_item(void *aconf)
138 {
139  struct ConfItem *conf;
140
141  conf = (struct ConfItem *)((uintptr_t)aconf -
142                             (uintptr_t)sizeof(struct ConfItem));
143  return(conf);
144 }
84  
85   /* conf_dns_callback()
86   *
87 < * inputs       - pointer to struct AccessItem
87 > * inputs       - pointer to struct MaskItem
88   *              - pointer to DNSReply reply
89   * output       - none
90   * side effects - called when resolver query finishes
# Line 154 | Line 93 | unmap_conf_item(void *aconf)
93   * if successful save hp in the conf item it was called with
94   */
95   static void
96 < conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
96 > conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name, size_t namelength)
97   {
98 <  struct AccessItem *aconf = vptr;
98 >  struct MaskItem *conf = vptr;
99  
100 <  aconf->dns_pending = 0;
100 >  conf->dns_pending = 0;
101  
102 <  if (addr != NULL)
103 <    memcpy(&aconf->addr, addr, sizeof(aconf->addr));
102 >  if (addr)
103 >    memcpy(&conf->addr, addr, sizeof(conf->addr));
104    else
105 <    aconf->dns_failed = 1;
105 >    conf->dns_failed = 1;
106   }
107  
108   /* conf_dns_lookup()
# Line 173 | Line 112 | conf_dns_callback(void *vptr, const stru
112   * allocate a dns_query and start ns lookup.
113   */
114   static void
115 < conf_dns_lookup(struct AccessItem *aconf)
115 > conf_dns_lookup(struct MaskItem *conf)
116   {
117 <  if (!aconf->dns_pending)
117 >  if (!conf->dns_pending)
118    {
119 <    aconf->dns_pending = 1;
120 <    gethost_byname(conf_dns_callback, aconf, aconf->host);
119 >    conf->dns_pending = 1;
120 >
121 >    if (conf->aftype == AF_INET)
122 >      gethost_byname_type(conf_dns_callback, conf, conf->host, T_A);
123 >    else
124 >      gethost_byname_type(conf_dns_callback, conf, conf->host, T_AAAA);
125    }
126   }
127  
128 < /* make_conf_item()
129 < *
187 < * inputs       - type of item
188 < * output       - pointer to new conf entry
189 < * side effects - none
190 < */
191 < struct ConfItem *
192 < make_conf_item(ConfType type)
128 > struct MaskItem *
129 > conf_make(enum maskitem_type type)
130   {
131 <  struct ConfItem *conf = NULL;
132 <  struct AccessItem *aconf = NULL;
196 <  struct ClassItem *aclass = NULL;
197 <  int status = 0;
198 <
199 <  switch (type)
200 <  {
201 <  case DLINE_TYPE:
202 <  case EXEMPTDLINE_TYPE:
203 <  case GLINE_TYPE:
204 <  case KLINE_TYPE:
205 <  case CLIENT_TYPE:
206 <  case OPER_TYPE:
207 <  case SERVER_TYPE:
208 <    conf = MyMalloc(sizeof(struct ConfItem) +
209 <                    sizeof(struct AccessItem));
210 <    aconf = map_to_conf(conf);
211 <    aconf->aftype = AF_INET;
212 <
213 <    /* Yes, sigh. switch on type again */
214 <    switch (type)
215 <    {
216 <    case EXEMPTDLINE_TYPE:
217 <      status = CONF_EXEMPTDLINE;
218 <      break;
219 <
220 <    case DLINE_TYPE:
221 <      status = CONF_DLINE;
222 <      break;
223 <
224 <    case KLINE_TYPE:
225 <      status = CONF_KLINE;
226 <      break;
227 <
228 <    case GLINE_TYPE:
229 <      status = CONF_GLINE;
230 <      break;
231 <
232 <    case CLIENT_TYPE:
233 <      status = CONF_CLIENT;
234 <      break;
235 <
236 <    case OPER_TYPE:
237 <      status = CONF_OPERATOR;
238 <      dlinkAdd(conf, &conf->node, &oconf_items);
239 <      break;
240 <
241 <    case SERVER_TYPE:
242 <      status = CONF_SERVER;
243 <      dlinkAdd(conf, &conf->node, &server_items);
244 <      break;
245 <
246 <    default:
247 <      break;
248 <    }
249 <    aconf->status = status;
250 <    break;
251 <
252 <  case ULINE_TYPE:
253 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
254 <                                       sizeof(struct MatchItem));
255 <    dlinkAdd(conf, &conf->node, &uconf_items);
256 <    break;
257 <
258 <  case GDENY_TYPE:
259 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
260 <                                       sizeof(struct AccessItem));
261 <    dlinkAdd(conf, &conf->node, &gdeny_items);
262 <    break;
263 <
264 <  case XLINE_TYPE:
265 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
266 <                                       sizeof(struct MatchItem));
267 <    dlinkAdd(conf, &conf->node, &xconf_items);
268 <    break;
269 < #ifdef HAVE_LIBPCRE
270 <  case RXLINE_TYPE:
271 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
272 <                                       sizeof(struct MatchItem));
273 <    dlinkAdd(conf, &conf->node, &rxconf_items);
274 <    break;
275 <
276 <  case RKLINE_TYPE:
277 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
278 <                                       sizeof(struct AccessItem));
279 <    aconf = map_to_conf(conf);
280 <    aconf->status = CONF_KLINE;
281 <    dlinkAdd(conf, &conf->node, &rkconf_items);
282 <    break;
283 < #endif
284 <  case CLUSTER_TYPE:
285 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
286 <    dlinkAdd(conf, &conf->node, &cluster_items);
287 <    break;
288 <
289 <  case CRESV_TYPE:
290 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
291 <                                       sizeof(struct ResvChannel));
292 <    break;
293 <
294 <  case NRESV_TYPE:
295 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
296 <                                       sizeof(struct MatchItem));
297 <    dlinkAdd(conf, &conf->node, &nresv_items);
298 <    break;
299 <
300 <  case SERVICE_TYPE:
301 <    status = CONF_SERVICE;
302 <    conf = MyMalloc(sizeof(struct ConfItem));
303 <    dlinkAdd(conf, &conf->node, &service_items);
304 <    break;
305 <
306 <  case CLASS_TYPE:
307 <    conf = MyMalloc(sizeof(struct ConfItem) +
308 <                           sizeof(struct ClassItem));
309 <    dlinkAdd(conf, &conf->node, &class_items);
310 <
311 <    aclass = map_to_conf(conf);
312 <    aclass->active = 1;
313 <    aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
314 <    aclass->ping_freq = DEFAULT_PINGFREQUENCY;
315 <    aclass->max_total = MAXIMUM_LINKS_DEFAULT;
316 <    aclass->max_sendq = DEFAULT_SENDQ;
317 <
318 <    break;
131 >  struct MaskItem *conf = MyCalloc(sizeof(*conf));
132 >  dlink_list *list = NULL;
133  
134 <  default:
135 <    conf = NULL;
136 <    break;
323 <  }
324 <
325 <  /* XXX Yes, this will core if default is hit. I want it to for now - db */
326 <  conf->type = type;
134 >  conf->type   = type;
135 >  conf->active = 1;
136 >  conf->aftype = AF_INET;
137  
138 +  if ((list = map_to_list(type)))
139 +    dlinkAdd(conf, &conf->node, list);
140    return conf;
141   }
142  
143   void
144 < delete_conf_item(struct ConfItem *conf)
144 > conf_free(struct MaskItem *conf)
145   {
146 <  dlink_node *m = NULL, *m_next = NULL;
147 <  struct MatchItem *match_item;
148 <  struct AccessItem *aconf;
149 <  ConfType type = conf->type;
146 >  dlink_node *ptr = NULL, *ptr_next = NULL;
147 >  dlink_list *list = NULL;
148 >
149 >  if ((list = map_to_list(conf->type)))
150 >    dlinkFindDelete(list, conf);
151  
152    MyFree(conf->name);
340  conf->name = NULL;
153  
154 <  switch(type)
155 <  {
156 <  case DLINE_TYPE:
157 <  case EXEMPTDLINE_TYPE:
158 <  case GLINE_TYPE:
159 <  case KLINE_TYPE:
160 <  case CLIENT_TYPE:
161 <  case OPER_TYPE:
162 <  case SERVER_TYPE:
163 <    aconf = map_to_conf(conf);
164 <
165 <    if (aconf->dns_pending)
166 <      delete_resolver_queries(aconf);
167 <    if (aconf->passwd != NULL)
168 <      memset(aconf->passwd, 0, strlen(aconf->passwd));
357 <    if (aconf->spasswd != NULL)
358 <      memset(aconf->spasswd, 0, strlen(aconf->spasswd));
359 <    aconf->class_ptr = NULL;
360 <
361 <    MyFree(aconf->passwd);
362 <    MyFree(aconf->spasswd);
363 <    MyFree(aconf->reason);
364 <    MyFree(aconf->oper_reason);
365 <    MyFree(aconf->user);
366 <    MyFree(aconf->host);
367 <    MyFree(aconf->cipher_list);
154 >  if (conf->dns_pending)
155 >    delete_resolver_queries(conf);
156 >  if (conf->passwd)
157 >    memset(conf->passwd, 0, strlen(conf->passwd));
158 >  if (conf->spasswd)
159 >    memset(conf->spasswd, 0, strlen(conf->spasswd));
160 >
161 >  conf->class = NULL;
162 >
163 >  MyFree(conf->passwd);
164 >  MyFree(conf->spasswd);
165 >  MyFree(conf->reason);
166 >  MyFree(conf->certfp);
167 >  MyFree(conf->user);
168 >  MyFree(conf->host);
169   #ifdef HAVE_LIBCRYPTO
170 <    if (aconf->rsa_public_key)
370 <      RSA_free(aconf->rsa_public_key);
371 <    MyFree(aconf->rsa_public_key_file);
372 < #endif
373 <
374 <    /* Yes, sigh. switch on type again */
375 <    switch(type)
376 <    {
377 <    case EXEMPTDLINE_TYPE:
378 <    case DLINE_TYPE:
379 <    case GLINE_TYPE:
380 <    case KLINE_TYPE:
381 <    case CLIENT_TYPE:
382 <      MyFree(conf);
383 <      break;
384 <
385 <    case OPER_TYPE:
386 <      aconf = map_to_conf(conf);
387 <      if (!IsConfIllegal(aconf))
388 <        dlinkDelete(&conf->node, &oconf_items);
389 <      MyFree(conf);
390 <      break;
170 >  MyFree(conf->cipher_list);
171  
172 <    case SERVER_TYPE:
173 <      aconf = map_to_conf(conf);
394 <
395 <      DLINK_FOREACH_SAFE(m, m_next, aconf->hub_list.head)
396 <      {
397 <        MyFree(m->data);
398 <        free_dlink_node(m);
399 <      }
400 <
401 <      DLINK_FOREACH_SAFE(m, m_next, aconf->leaf_list.head)
402 <      {
403 <        MyFree(m->data);
404 <        free_dlink_node(m);  
405 <      }
406 <
407 <      if (!IsConfIllegal(aconf))
408 <        dlinkDelete(&conf->node, &server_items);
409 <      MyFree(conf);
410 <      break;
411 <
412 <    default:
413 <      break;
414 <    }
415 <    break;
416 <
417 <  case ULINE_TYPE:
418 <    match_item = map_to_conf(conf);
419 <    MyFree(match_item->user);
420 <    MyFree(match_item->host);
421 <    MyFree(match_item->reason);
422 <    MyFree(match_item->oper_reason);
423 <    dlinkDelete(&conf->node, &uconf_items);
424 <    MyFree(conf);
425 <    break;
426 <
427 <  case XLINE_TYPE:
428 <    match_item = map_to_conf(conf);
429 <    MyFree(match_item->user);
430 <    MyFree(match_item->host);
431 <    MyFree(match_item->reason);
432 <    MyFree(match_item->oper_reason);
433 <    dlinkDelete(&conf->node, &xconf_items);
434 <    MyFree(conf);
435 <    break;
436 < #ifdef HAVE_LIBPCRE
437 <  case RKLINE_TYPE:
438 <    aconf = map_to_conf(conf);
439 <    MyFree(aconf->regexuser);
440 <    MyFree(aconf->regexhost);
441 <    MyFree(aconf->user);
442 <    MyFree(aconf->host);
443 <    MyFree(aconf->reason);
444 <    MyFree(aconf->oper_reason);
445 <    dlinkDelete(&conf->node, &rkconf_items);
446 <    MyFree(conf);
447 <    break;
448 <
449 <  case RXLINE_TYPE:
450 <    MyFree(conf->regexpname);
451 <    match_item = map_to_conf(conf);
452 <    MyFree(match_item->user);
453 <    MyFree(match_item->host);
454 <    MyFree(match_item->reason);
455 <    MyFree(match_item->oper_reason);
456 <    dlinkDelete(&conf->node, &rxconf_items);
457 <    MyFree(conf);
458 <    break;
172 >  if (conf->rsa_public_key)
173 >    RSA_free(conf->rsa_public_key);
174   #endif
175 <  case NRESV_TYPE:
176 <    match_item = map_to_conf(conf);
177 <    MyFree(match_item->user);
178 <    MyFree(match_item->host);
179 <    MyFree(match_item->reason);
465 <    MyFree(match_item->oper_reason);
466 <    dlinkDelete(&conf->node, &nresv_items);
467 <
468 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
469 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
470 <        free_dlink_node(m);
471 <
472 <    MyFree(conf);
473 <    break;
474 <
475 <  case GDENY_TYPE:
476 <    aconf = map_to_conf(conf);
477 <    MyFree(aconf->user);
478 <    MyFree(aconf->host);
479 <    dlinkDelete(&conf->node, &gdeny_items);
480 <    MyFree(conf);
481 <    break;
482 <
483 <  case CLUSTER_TYPE:
484 <    dlinkDelete(&conf->node, &cluster_items);
485 <    MyFree(conf);
486 <    break;
487 <
488 <  case CRESV_TYPE:
489 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
490 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
491 <        free_dlink_node(m);
492 <
493 <    MyFree(conf);
494 <    break;
495 <
496 <  case CLASS_TYPE:
497 <    dlinkDelete(&conf->node, &class_items);
498 <    MyFree(conf);
499 <    break;
500 <
501 <  case SERVICE_TYPE:
502 <    dlinkDelete(&conf->node, &service_items);
503 <    MyFree(conf);
504 <    break;
505 <
506 <  default:
507 <    break;
175 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->hub_list.head)
176 >  {
177 >    MyFree(ptr->data);
178 >    dlinkDelete(ptr, &conf->hub_list);
179 >    free_dlink_node(ptr);
180    }
509 }
510
511 /* free_access_item()
512 *
513 * inputs       - pointer to conf to free
514 * output       - none
515 * side effects - crucial password fields are zeroed, conf is freed
516 */
517 void
518 free_access_item(struct AccessItem *aconf)
519 {
520  struct ConfItem *conf;
521
522  if (aconf == NULL)
523    return;
524  conf = unmap_conf_item(aconf);
525  delete_conf_item(conf);
526 }
527
528 static const unsigned int shared_bit_table[] =
529  { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
181  
182 < /* report_confitem_types()
532 < *
533 < * inputs       - pointer to client requesting confitem report
534 < *              - ConfType to report
535 < * output       - none
536 < * side effects -
537 < */
538 < void
539 < report_confitem_types(struct Client *source_p, ConfType type)
540 < {
541 <  dlink_node *ptr = NULL, *dptr = NULL;
542 <  struct ConfItem *conf = NULL;
543 <  struct AccessItem *aconf = NULL;
544 <  struct MatchItem *matchitem = NULL;
545 <  struct ClassItem *classitem = NULL;
546 <  char buf[12];
547 <  char *p = NULL;
548 <
549 <  switch (type)
182 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->leaf_list.head)
183    {
184 <  case GDENY_TYPE:
185 <    DLINK_FOREACH(ptr, gdeny_items.head)
186 <    {
187 <      conf = ptr->data;
555 <      aconf = map_to_conf(conf);
556 <
557 <      p = buf;
558 <
559 <      if (aconf->flags & GDENY_BLOCK)
560 <        *p++ = 'B';
561 <      else
562 <        *p++ = 'b';
563 <
564 <      if (aconf->flags & GDENY_REJECT)
565 <        *p++ = 'R';
566 <      else
567 <        *p++ = 'r';
568 <
569 <      *p = '\0';
570 <
571 <      sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
572 <                 me.name, RPL_STATSDEBUG, source_p->name,
573 <                 aconf->user, aconf->host, conf->name, buf);
574 <    }
575 <    break;
576 <
577 <  case XLINE_TYPE:
578 <    DLINK_FOREACH(ptr, xconf_items.head)
579 <    {
580 <      conf = ptr->data;
581 <      matchitem = map_to_conf(conf);
582 <
583 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
584 <                 me.name, source_p->name,
585 <                 matchitem->hold ? "x": "X", matchitem->count,
586 <                 conf->name, matchitem->reason);
587 <    }
588 <    break;
589 <
590 < #ifdef HAVE_LIBPCRE
591 <  case RXLINE_TYPE:
592 <    DLINK_FOREACH(ptr, rxconf_items.head)
593 <    {
594 <      conf = ptr->data;
595 <      matchitem = map_to_conf(conf);
596 <
597 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
598 <                 me.name, source_p->name,
599 <                 "XR", matchitem->count,
600 <                 conf->name, matchitem->reason);
601 <    }
602 <    break;
603 <
604 <  case RKLINE_TYPE:
605 <    DLINK_FOREACH(ptr, rkconf_items.head)
606 <    {
607 <      aconf = map_to_conf((conf = ptr->data));
608 <
609 <      sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
610 <                 source_p->name, "KR", aconf->host, aconf->user,
611 <                 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
612 <    }
613 <    break;
614 < #endif
615 <
616 <  case ULINE_TYPE:
617 <    DLINK_FOREACH(ptr, uconf_items.head)
618 <    {
619 <      conf = ptr->data;
620 <      matchitem = map_to_conf(conf);
621 <
622 <      p = buf;
623 <
624 <      /* some of these are redundant for the sake of
625 <       * consistency with cluster{} flags
626 <       */
627 <      *p++ = 'c';
628 <      flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
629 <
630 <      sendto_one(source_p, form_str(RPL_STATSULINE),
631 <                 me.name, source_p->name, conf->name,
632 <                 matchitem->user?matchitem->user: "*",
633 <                 matchitem->host?matchitem->host: "*", buf);
634 <    }
635 <
636 <    DLINK_FOREACH(ptr, cluster_items.head)
637 <    {
638 <      conf = ptr->data;
639 <
640 <      p = buf;
641 <
642 <      *p++ = 'C';
643 <      flags_to_ascii(conf->flags, shared_bit_table, p, 0);
644 <
645 <      sendto_one(source_p, form_str(RPL_STATSULINE),
646 <                 me.name, source_p->name, conf->name,
647 <                 "*", "*", buf);
648 <    }
649 <
650 <    break;
651 <
652 <  case OPER_TYPE:
653 <    DLINK_FOREACH(ptr, oconf_items.head)
654 <    {
655 <      conf = ptr->data;
656 <      aconf = map_to_conf(conf);
657 <
658 <      /* Don't allow non opers to see oper privs */
659 <      if (HasUMode(source_p, UMODE_OPER))
660 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
661 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
662 <                   conf->name, oper_privs_as_string(aconf->port),
663 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
664 <      else
665 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
666 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
667 <                   conf->name, "0",
668 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
669 <    }
670 <    break;
671 <
672 <  case CLASS_TYPE:
673 <    DLINK_FOREACH(ptr, class_items.head)
674 <    {
675 <      conf = ptr->data;
676 <      classitem = map_to_conf(conf);
677 <      sendto_one(source_p, form_str(RPL_STATSYLINE),
678 <                 me.name, source_p->name, 'Y',
679 <                 conf->name, classitem->ping_freq,
680 <                 classitem->con_freq,
681 <                 classitem->max_total, classitem->max_sendq,
682 <                 classitem->curr_user_count,
683 <                 classitem->active ? "active" : "disabled");
684 <    }
685 <    break;
686 <
687 <  case CONF_TYPE:
688 <  case CLIENT_TYPE:
689 <    break;
690 <
691 <  case SERVICE_TYPE:
692 <    DLINK_FOREACH(ptr, service_items.head)
693 <    {
694 <      conf = ptr->data;
695 <      sendto_one(source_p, form_str(RPL_STATSSERVICE),
696 <                 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
697 <    }
698 <    break;
699 <
700 <  case SERVER_TYPE:
701 <    DLINK_FOREACH(ptr, server_items.head)
702 <    {
703 <      p = buf;
704 <
705 <      conf = ptr->data;
706 <      aconf = map_to_conf(conf);
707 <
708 <      buf[0] = '\0';
709 <
710 <      if (IsConfAllowAutoConn(aconf))
711 <        *p++ = 'A';
712 <      if (IsConfSSL(aconf))
713 <        *p++ = 'S';
714 <      if (IsConfTopicBurst(aconf))
715 <        *p++ = 'T';
716 <      if (buf[0] == '\0')
717 <        *p++ = '*';
718 <
719 <      *p = '\0';
720 <
721 <      /*
722 <       * Allow admins to see actual ips unless hide_server_ips is enabled
723 <       */
724 <      if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
725 <        sendto_one(source_p, form_str(RPL_STATSCLINE),
726 <                   me.name, source_p->name, 'C', aconf->host,
727 <                   buf, conf->name, aconf->port,
728 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
729 <        else
730 <          sendto_one(source_p, form_str(RPL_STATSCLINE),
731 <                     me.name, source_p->name, 'C',
732 <                     "*@127.0.0.1", buf, conf->name, aconf->port,
733 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
734 <    }
735 <    break;
736 <
737 <  case HUB_TYPE:
738 <    DLINK_FOREACH(ptr, server_items.head)
739 <    {
740 <      conf = ptr->data;
741 <      aconf = map_to_conf(conf);
742 <
743 <      DLINK_FOREACH(dptr, aconf->hub_list.head)
744 <        sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
745 <                   source_p->name, 'H', dptr->data, conf->name, 0, "*");
746 <    }
747 <    break;
748 <
749 <  case LEAF_TYPE:
750 <    DLINK_FOREACH(ptr, server_items.head)
751 <    {
752 <      conf = ptr->data;
753 <      aconf = map_to_conf(conf);
184 >    MyFree(ptr->data);
185 >    dlinkDelete(ptr, &conf->leaf_list);
186 >    free_dlink_node(ptr);
187 >  }
188  
189 <      DLINK_FOREACH(dptr, aconf->leaf_list.head)
190 <        sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
191 <                   source_p->name, 'L', dptr->data, conf->name, 0, "*");
758 <    }
759 <    break;
189 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->exempt_list.head)
190 >  {
191 >    struct exempt *exptr = ptr->data;
192  
193 <  case GLINE_TYPE:
194 <  case KLINE_TYPE:
195 <  case DLINE_TYPE:
196 <  case EXEMPTDLINE_TYPE:
197 <  case CRESV_TYPE:
766 <  case NRESV_TYPE:
767 <  case CLUSTER_TYPE:
768 <  default:
769 <    break;
193 >    dlinkDelete(ptr, &conf->exempt_list);
194 >    MyFree(exptr->name);
195 >    MyFree(exptr->user);
196 >    MyFree(exptr->host);
197 >    MyFree(exptr);
198    }
199 +
200 +  MyFree(conf);
201   }
202  
203   /* check_client()
# Line 783 | Line 213 | report_confitem_types(struct Client *sou
213   *                Look for conf lines which have the same
214   *                status as the flags passed.
215   */
216 < static void *
217 < check_client(va_list args)
216 > int
217 > check_client(struct Client *source_p)
218   {
789  struct Client *source_p = va_arg(args, struct Client *);
790  const char *username = va_arg(args, const char *);
219    int i;
220 <
221 <  /* I'm already in big trouble if source_p->localClient is NULL -db */
222 <  if ((i = verify_access(source_p, username)))
795 <    ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
220 >
221 >  if ((i = verify_access(source_p)))
222 >    ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
223           source_p->name, source_p->sockhost);
224  
225    switch (i)
226    {
227      case TOO_MANY:
228 <      sendto_realops_flags(UMODE_FULL, L_ALL,
228 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
229                             "Too many on IP for %s (%s).",
230 <                           get_client_name(source_p, SHOW_IP),
231 <                           source_p->sockhost);
230 >                           get_client_name(source_p, SHOW_IP),
231 >                           source_p->sockhost);
232        ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
233 <           get_client_name(source_p, SHOW_IP));
233 >           get_client_name(source_p, SHOW_IP));
234        ++ServerStats.is_ref;
235 <      exit_client(source_p, &me, "No more connections allowed on that IP");
235 >      exit_client(source_p, "No more connections allowed on that IP");
236        break;
237  
238      case I_LINE_FULL:
239 <      sendto_realops_flags(UMODE_FULL, L_ALL,
240 <                           "I-line is full for %s (%s).",
241 <                           get_client_name(source_p, SHOW_IP),
242 <                           source_p->sockhost);
239 >      sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
240 >                           "auth{} block is full for %s (%s).",
241 >                           get_client_name(source_p, SHOW_IP),
242 >                           source_p->sockhost);
243        ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
244 <           get_client_name(source_p, SHOW_IP));
244 >           get_client_name(source_p, SHOW_IP));
245        ++ServerStats.is_ref;
246 <      exit_client(source_p, &me,
820 <                "No more connections allowed in your connection class");
246 >      exit_client(source_p, "No more connections allowed in your connection class");
247        break;
248  
249      case NOT_AUTHORIZED:
250        ++ServerStats.is_ref;
251        /* jdc - lists server name & port connections are on */
252        /*       a purely cosmetical change */
253 <      sendto_realops_flags(UMODE_UNAUTH, L_ALL,
254 <                           "Unauthorized client connection from %s [%s] on [%s/%u].",
255 <                           get_client_name(source_p, SHOW_IP),
256 <                           source_p->sockhost,
257 <                           source_p->localClient->listener->name,
258 <                           source_p->localClient->listener->port);
253 >      sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
254 >                           "Unauthorized client connection from %s [%s] on [%s/%u].",
255 >                           get_client_name(source_p, SHOW_IP),
256 >                           source_p->sockhost,
257 >                           source_p->connection->listener->name,
258 >                           source_p->connection->listener->port);
259        ilog(LOG_TYPE_IRCD,
260 <          "Unauthorized client connection from %s on [%s/%u].",
261 <          get_client_name(source_p, SHOW_IP),
262 <          source_p->localClient->listener->name,
263 <          source_p->localClient->listener->port);
264 <
265 <      /* XXX It is prolematical whether it is better to use the
840 <       * capture reject code here or rely on the connecting too fast code.
841 <       * - Dianora
842 <       */
843 <      if (REJECT_HOLD_TIME > 0)
844 <      {
845 <        sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
846 <                   me.name, source_p->name);
847 <        source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
848 <        SetCaptured(source_p);
849 <      }
850 <      else
851 <        exit_client(source_p, &me, "You are not authorized to use this server");
260 >           "Unauthorized client connection from %s on [%s/%u].",
261 >           get_client_name(source_p, SHOW_IP),
262 >           source_p->connection->listener->name,
263 >           source_p->connection->listener->port);
264 >
265 >      exit_client(source_p, "You are not authorized to use this server");
266        break;
267  
268     case BANNED_CLIENT:
269 <     /*
856 <      * Don't exit them immediately, play with them a bit.
857 <      * - Dianora
858 <      */
859 <     if (REJECT_HOLD_TIME > 0)
860 <     {
861 <       source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
862 <       SetCaptured(source_p);
863 <     }
864 <     else
865 <       exit_client(source_p, &me, "Banned");
269 >     exit_client(source_p, "Banned");
270       ++ServerStats.is_ref;
271       break;
272  
# Line 871 | Line 275 | check_client(va_list args)
275       break;
276    }
277  
278 <  return (i < 0 ? NULL : source_p);
278 >  return (i < 0 ? 0 : 1);
279   }
280  
281   /* verify_access()
282   *
283   * inputs       - pointer to client to verify
880 *              - pointer to proposed username
284   * output       - 0 if success -'ve if not
285   * side effect  - find the first (best) I line to attach.
286   */
287   static int
288 < verify_access(struct Client *client_p, const char *username)
288 > verify_access(struct Client *client_p)
289   {
290 <  struct AccessItem *aconf = NULL, *rkconf = NULL;
291 <  struct ConfItem *conf = NULL;
889 <  char non_ident[USERLEN + 1] = { '~', '\0' };
890 <  const char *uhi[3];
290 >  struct MaskItem *conf = NULL;
291 >  char non_ident[USERLEN + 1] = "~";
292  
293    if (IsGotId(client_p))
294    {
295 <    aconf = find_address_conf(client_p->host, client_p->username,
296 <                             &client_p->localClient->ip,
297 <                             client_p->localClient->aftype,
298 <                             client_p->localClient->passwd);
295 >    conf = find_address_conf(client_p->host, client_p->username,
296 >                             &client_p->connection->ip,
297 >                             client_p->connection->aftype,
298 >                             client_p->connection->password);
299    }
300    else
301    {
302 <    strlcpy(non_ident+1, username, sizeof(non_ident)-1);
303 <    aconf = find_address_conf(client_p->host,non_ident,
304 <                             &client_p->localClient->ip,
305 <                             client_p->localClient->aftype,
306 <                             client_p->localClient->passwd);
302 >    strlcpy(non_ident + 1, client_p->username, sizeof(non_ident) - 1);
303 >    conf = find_address_conf(client_p->host,non_ident,
304 >                             &client_p->connection->ip,
305 >                             client_p->connection->aftype,
306 >                             client_p->connection->password);
307    }
308  
309 <  uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
909 <  uhi[1] = client_p->host;
910 <  uhi[2] = client_p->sockhost;
911 <
912 <  rkconf = find_regexp_kline(uhi);
913 <
914 <  if (aconf != NULL)
309 >  if (conf)
310    {
311 <    if (IsConfClient(aconf) && !rkconf)
311 >    if (IsConfClient(conf))
312      {
313 <      conf = unmap_conf_item(aconf);
919 <
920 <      if (IsConfRedir(aconf))
313 >      if (IsConfRedir(conf))
314        {
315 <        sendto_one(client_p, form_str(RPL_REDIR),
316 <                   me.name, client_p->name,
317 <                   conf->name ? conf->name : "",
318 <                   aconf->port);
926 <        return(NOT_AUTHORIZED);
315 >        sendto_one_numeric(client_p, &me, RPL_REDIR,
316 >                           conf->name ? conf->name : "",
317 >                           conf->port);
318 >        return NOT_AUTHORIZED;
319        }
320  
321 <      if (IsConfDoIdentd(aconf))
322 <        SetNeedId(client_p);
321 >      if (IsConfDoIdentd(conf))
322 >        SetNeedId(client_p);
323  
324        /* Thanks for spoof idea amm */
325 <      if (IsConfDoSpoofIp(aconf))
325 >      if (IsConfDoSpoofIp(conf))
326        {
327 <        conf = unmap_conf_item(aconf);
328 <
329 <        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
938 <          sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
327 >        if (!ConfigGeneral.hide_spoof_ips && IsConfSpoofNotice(conf))
328 >          sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
329 >                               "%s spoofing: %s as %s",
330                                 client_p->name, client_p->host, conf->name);
331          strlcpy(client_p->host, conf->name, sizeof(client_p->host));
332 <        SetIPSpoof(client_p);
332 >        AddFlag(client_p, FLAGS_IP_SPOOFING | FLAGS_AUTH_SPOOF);
333        }
334  
335 <      return(attach_iline(client_p, conf));
335 >      return attach_iline(client_p, conf);
336      }
337 <    else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
337 >    else if (IsConfKill(conf) || (ConfigGeneral.glines && IsConfGline(conf)))
338      {
339 <      /* XXX */
340 <      aconf = rkconf ? rkconf : aconf;
341 <      if (IsConfGline(aconf))
342 <        sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
952 <                   client_p->name);
953 <      if (ConfigFileEntry.kline_with_reason)
954 <        sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
955 <                  me.name, client_p->name, aconf->reason);
956 <      return(BANNED_CLIENT);
339 >      if (IsConfGline(conf))
340 >        sendto_one_notice(client_p, &me, ":*** G-lined");
341 >      sendto_one_notice(client_p, &me, ":*** Banned: %s", conf->reason);
342 >      return BANNED_CLIENT;
343      }
344    }
345  
346 <  return(NOT_AUTHORIZED);
346 >  return NOT_AUTHORIZED;
347   }
348  
349   /* attach_iline()
# Line 968 | Line 354 | verify_access(struct Client *client_p, c
354   * side effects - do actual attach
355   */
356   static int
357 < attach_iline(struct Client *client_p, struct ConfItem *conf)
357 > attach_iline(struct Client *client_p, struct MaskItem *conf)
358   {
359 <  struct AccessItem *aconf;
974 <  struct ClassItem *aclass;
359 >  const struct ClassItem *class = conf->class;
360    struct ip_entry *ip_found;
361    int a_limit_reached = 0;
362 <  int local = 0, global = 0, ident = 0;
362 >  unsigned int local = 0, global = 0, ident = 0;
363  
364 <  ip_found = find_or_add_ip(&client_p->localClient->ip);
364 >  ip_found = ipcache_find_or_add_address(&client_p->connection->ip);
365    ip_found->count++;
366 <  SetIpHash(client_p);
982 <
983 <  aconf = map_to_conf(conf);
984 <  if (aconf->class_ptr == NULL)
985 <    return NOT_AUTHORIZED;  /* If class is missing, this is best */
986 <
987 <  aclass = map_to_conf(aconf->class_ptr);
366 >  AddFlag(client_p, FLAGS_IPHASH);
367  
368    count_user_host(client_p->username, client_p->host,
369                    &global, &local, &ident);
# Line 993 | Line 372 | attach_iline(struct Client *client_p, st
372     * setting a_limit_reached if any limit is reached.
373     * - Dianora
374     */
375 <  if (aclass->max_total != 0 && aclass->curr_user_count >= aclass->max_total)
375 >  if (class->max_total && class->ref_count >= class->max_total)
376      a_limit_reached = 1;
377 <  else if (aclass->max_perip != 0 && ip_found->count > aclass->max_perip)
377 >  else if (class->max_perip && ip_found->count > class->max_perip)
378      a_limit_reached = 1;
379 <  else if (aclass->max_local != 0 && local >= aclass->max_local)
379 >  else if (class->max_local && local >= class->max_local)
380      a_limit_reached = 1;
381 <  else if (aclass->max_global != 0 && global >= aclass->max_global)
381 >  else if (class->max_global && global >= class->max_global)
382      a_limit_reached = 1;
383 <  else if (aclass->max_ident != 0 && ident >= aclass->max_ident &&
383 >  else if (class->max_ident && ident >= class->max_ident &&
384             client_p->username[0] != '~')
385      a_limit_reached = 1;
386  
387    if (a_limit_reached)
388    {
389 <    if (!IsConfExemptLimits(aconf))
389 >    if (!IsConfExemptLimits(conf))
390        return TOO_MANY;   /* Already at maximum allowed */
391  
392 <    sendto_one(client_p,
393 <               ":%s NOTICE %s :*** Your connection class is full, "
1015 <               "but you have exceed_limit = yes;", me.name, client_p->name);
392 >    sendto_one_notice(client_p, &me, ":*** Your connection class is full, "
393 >                      "but you have exceed_limit = yes;");
394    }
395  
396    return attach_conf(client_p, conf);
397   }
398  
1021 /* init_ip_hash_table()
1022 *
1023 * inputs               - NONE
1024 * output               - NONE
1025 * side effects         - allocate memory for ip_entry(s)
1026 *                      - clear the ip hash table
1027 */
1028 void
1029 init_ip_hash_table(void)
1030 {
1031  ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
1032    2 * hard_fdlimit);
1033  memset(ip_hash_table, 0, sizeof(ip_hash_table));
1034 }
1035
1036 /* find_or_add_ip()
1037 *
1038 * inputs       - pointer to struct irc_ssaddr
1039 * output       - pointer to a struct ip_entry
1040 * side effects -
1041 *
1042 * If the ip # was not found, a new struct ip_entry is created, and the ip
1043 * count set to 0.
1044 */
1045 static struct ip_entry *
1046 find_or_add_ip(struct irc_ssaddr *ip_in)
1047 {
1048  struct ip_entry *ptr, *newptr;
1049  int hash_index = hash_ip(ip_in), res;
1050  struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1051 #ifdef IPV6
1052  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1053 #endif
1054
1055  for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1056  {
1057 #ifdef IPV6
1058    if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1059      continue;
1060    if (ip_in->ss.ss_family == AF_INET6)
1061    {
1062      ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1063      res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1064    }
1065    else
1066 #endif
1067    {
1068      ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1069      res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1070    }
1071    if (res == 0)
1072    {
1073      /* Found entry already in hash, return it. */
1074      return ptr;
1075    }
1076  }
1077
1078  if (ip_entries_count >= 2 * hard_fdlimit)
1079    garbage_collect_ip_entries();
1080
1081  newptr = BlockHeapAlloc(ip_entry_heap);
1082  ip_entries_count++;
1083  memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
1084
1085  newptr->next = ip_hash_table[hash_index];
1086  ip_hash_table[hash_index] = newptr;
1087
1088  return newptr;
1089 }
1090
1091 /* remove_one_ip()
1092 *
1093 * inputs        - unsigned long IP address value
1094 * output        - NONE
1095 * side effects  - The ip address given, is looked up in ip hash table
1096 *                 and number of ip#'s for that ip decremented.
1097 *                 If ip # count reaches 0 and has expired,
1098 *                 the struct ip_entry is returned to the ip_entry_heap
1099 */
1100 void
1101 remove_one_ip(struct irc_ssaddr *ip_in)
1102 {
1103  struct ip_entry *ptr;
1104  struct ip_entry *last_ptr = NULL;
1105  int hash_index = hash_ip(ip_in), res;
1106  struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1107 #ifdef IPV6
1108  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1109 #endif
1110
1111  for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1112  {
1113 #ifdef IPV6
1114    if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1115      continue;
1116    if (ip_in->ss.ss_family == AF_INET6)
1117    {
1118      ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1119      res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1120    }
1121    else
1122 #endif
1123    {
1124      ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1125      res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1126    }
1127    if (res)
1128      continue;
1129    if (ptr->count > 0)
1130      ptr->count--;
1131    if (ptr->count == 0 &&
1132        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1133    {
1134      if (last_ptr != NULL)
1135        last_ptr->next = ptr->next;
1136      else
1137        ip_hash_table[hash_index] = ptr->next;
1138
1139      BlockHeapFree(ip_entry_heap, ptr);
1140      ip_entries_count--;
1141      return;
1142    }
1143    last_ptr = ptr;
1144  }
1145 }
1146
1147 /* hash_ip()
1148 *
1149 * input        - pointer to an irc_inaddr
1150 * output       - integer value used as index into hash table
1151 * side effects - hopefully, none
1152 */
1153 static int
1154 hash_ip(struct irc_ssaddr *addr)
1155 {
1156  if (addr->ss.ss_family == AF_INET)
1157  {
1158    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
1159    int hash;
1160    uint32_t ip;
1161
1162    ip   = ntohl(v4->sin_addr.s_addr);
1163    hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
1164    return hash;
1165  }
1166 #ifdef IPV6
1167  else
1168  {
1169    int hash;
1170    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
1171    uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
1172
1173    hash  = ip[0] ^ ip[3];
1174    hash ^= hash >> 16;  
1175    hash ^= hash >> 8;  
1176    hash  = hash & (IP_HASH_SIZE - 1);
1177    return hash;
1178  }
1179 #else
1180  return 0;
1181 #endif
1182 }
1183
1184 /* count_ip_hash()
1185 *
1186 * inputs        - pointer to counter of number of ips hashed
1187 *               - pointer to memory used for ip hash
1188 * output        - returned via pointers input
1189 * side effects  - NONE
1190 *
1191 * number of hashed ip #'s is counted up, plus the amount of memory
1192 * used in the hash.
1193 */
1194 void
1195 count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
1196 {
1197  struct ip_entry *ptr;
1198  int i;
1199
1200  *number_ips_stored = 0;
1201  *mem_ips_stored    = 0;
1202
1203  for (i = 0; i < IP_HASH_SIZE; i++)
1204  {
1205    for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
1206    {
1207      *number_ips_stored += 1;
1208      *mem_ips_stored += sizeof(struct ip_entry);
1209    }
1210  }
1211 }
1212
1213 /* garbage_collect_ip_entries()
1214 *
1215 * input        - NONE
1216 * output       - NONE
1217 * side effects - free up all ip entries with no connections
1218 */
1219 static void
1220 garbage_collect_ip_entries(void)
1221 {
1222  struct ip_entry *ptr;
1223  struct ip_entry *last_ptr;
1224  struct ip_entry *next_ptr;
1225  int i;
1226
1227  for (i = 0; i < IP_HASH_SIZE; i++)
1228  {
1229    last_ptr = NULL;
1230
1231    for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
1232    {
1233      next_ptr = ptr->next;
1234
1235      if (ptr->count == 0 &&
1236          (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1237      {
1238        if (last_ptr != NULL)
1239          last_ptr->next = ptr->next;
1240        else
1241          ip_hash_table[i] = ptr->next;
1242        BlockHeapFree(ip_entry_heap, ptr);
1243        ip_entries_count--;
1244      }
1245      else
1246        last_ptr = ptr;
1247    }
1248  }
1249 }
1250
399   /* detach_conf()
400   *
401   * inputs       - pointer to client to detach
# Line 1256 | Line 404 | garbage_collect_ip_entries(void)
404   * side effects - Disassociate configuration from the client.
405   *                Also removes a class from the list if marked for deleting.
406   */
407 < int
408 < detach_conf(struct Client *client_p, ConfType type)
407 > void
408 > detach_conf(struct Client *client_p, enum maskitem_type type)
409   {
410 <  dlink_node *ptr, *next_ptr;
1263 <  struct ConfItem *conf;
1264 <  struct ClassItem *aclass;
1265 <  struct AccessItem *aconf;
1266 <  struct ConfItem *aclass_conf;
1267 <  struct MatchItem *match_item;
410 >  dlink_node *ptr = NULL, *ptr_next = NULL;
411  
412 <  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
412 >  DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->connection->confs.head)
413    {
414 <    conf = ptr->data;
1272 <
1273 <    if (type == CONF_TYPE || conf->type == type)
1274 <    {
1275 <      dlinkDelete(ptr, &client_p->localClient->confs);
1276 <      free_dlink_node(ptr);
1277 <
1278 <      switch (conf->type)
1279 <      {
1280 <      case CLIENT_TYPE:
1281 <      case OPER_TYPE:
1282 <      case SERVER_TYPE:
1283 <        aconf = map_to_conf(conf);
1284 <
1285 <        assert(aconf->clients > 0);
414 >    struct MaskItem *conf = ptr->data;
415  
416 <        if ((aclass_conf = aconf->class_ptr) != NULL)
417 <        {
418 <          aclass = map_to_conf(aclass_conf);
416 >    assert(conf->type & (CONF_CLIENT | CONF_OPER | CONF_SERVER));
417 >    assert(conf->ref_count > 0);
418 >    assert(conf->class->ref_count > 0);
419  
420 <          assert(aclass->curr_user_count > 0);
420 >    if (!(conf->type & type))
421 >      continue;
422  
423 <          if (conf->type == CLIENT_TYPE)
424 <            remove_from_cidr_check(&client_p->localClient->ip, aclass);
1295 <          if (--aclass->curr_user_count == 0 && aclass->active == 0)
1296 <            delete_conf_item(aclass_conf);
1297 <        }
423 >    dlinkDelete(ptr, &client_p->connection->confs);
424 >    free_dlink_node(ptr);
425  
426 <        if (--aconf->clients == 0 && IsConfIllegal(aconf))
427 <          delete_conf_item(conf);
426 >    if (conf->type == CONF_CLIENT)
427 >      remove_from_cidr_check(&client_p->connection->ip, conf->class);
428  
429 <        break;
430 <      default:
431 <        break;
432 <      }
1306 <
1307 <      if (type != CONF_TYPE)
1308 <        return 0;
429 >    if (--conf->class->ref_count == 0 && conf->class->active == 0)
430 >    {
431 >      class_free(conf->class);
432 >      conf->class = NULL;
433      }
1310  }
434  
435 <  return -1;
435 >    if (--conf->ref_count == 0 && conf->active == 0)
436 >      conf_free(conf);
437 >  }
438   }
439  
440   /* attach_conf()
# Line 1323 | Line 448 | detach_conf(struct Client *client_p, Con
448   *                attachment if there was an old one...
449   */
450   int
451 < attach_conf(struct Client *client_p, struct ConfItem *conf)
451 > attach_conf(struct Client *client_p, struct MaskItem *conf)
452   {
453 <  if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
453 >  if (dlinkFind(&client_p->connection->confs, conf))
454      return 1;
455  
456 <  if (conf->type == CLIENT_TYPE ||
457 <      conf->type == SERVER_TYPE ||
458 <      conf->type == OPER_TYPE)
459 <  {
1335 <    struct AccessItem *aconf = map_to_conf(conf);
1336 <    struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1337 <
1338 <    if (IsConfIllegal(aconf))
1339 <      return NOT_AUTHORIZED;
456 >  if (conf->type == CONF_CLIENT)
457 >    if (cidr_limit_reached(IsConfExemptLimits(conf),
458 >                           &client_p->connection->ip, conf->class))
459 >      return TOO_MANY;    /* Already at maximum allowed */
460  
461 <    if (conf->type == CLIENT_TYPE)
462 <      if (cidr_limit_reached(IsConfExemptLimits(aconf),
1343 <                             &client_p->localClient->ip, aclass))
1344 <        return TOO_MANY;    /* Already at maximum allowed */
461 >  conf->class->ref_count++;
462 >  conf->ref_count++;
463  
464 <    aclass->curr_user_count++;
1347 <    aconf->clients++;
1348 <  }
1349 <
1350 <  dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
464 >  dlinkAdd(conf, make_dlink_node(), &client_p->connection->confs);
465  
466    return 0;
467   }
# Line 1365 | Line 479 | attach_connect_block(struct Client *clie
479                       const char *host)
480   {
481    dlink_node *ptr;
482 <  struct ConfItem *conf;
1369 <  struct AccessItem *aconf;
482 >  struct MaskItem *conf = NULL;
483  
484    assert(client_p != NULL);
485    assert(host != NULL);
# Line 1377 | Line 490 | attach_connect_block(struct Client *clie
490    DLINK_FOREACH(ptr, server_items.head)
491    {
492      conf = ptr->data;
1380    aconf = map_to_conf(conf);
493  
494 <    if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
494 >    if (match(conf->name, name) || match(conf->host, host))
495        continue;
496  
497      attach_conf(client_p, conf);
# Line 1389 | Line 501 | attach_connect_block(struct Client *clie
501    return 0;
502   }
503  
1392 /* find_conf_exact()
1393 *
1394 * inputs       - type of ConfItem
1395 *              - pointer to name to find
1396 *              - pointer to username to find
1397 *              - pointer to host to find
1398 * output       - NULL or pointer to conf found
1399 * side effects - find a conf entry which matches the hostname
1400 *                and has the same name.
1401 */
1402 struct ConfItem *
1403 find_conf_exact(ConfType type, const char *name, const char *user,
1404                const char *host)
1405 {
1406  dlink_node *ptr;
1407  dlink_list *list_p;
1408  struct ConfItem *conf = NULL;
1409  struct AccessItem *aconf;
1410
1411  /* Only valid for OPER_TYPE and ...? */
1412  list_p = map_to_list(type);
1413
1414  DLINK_FOREACH(ptr, (*list_p).head)
1415  {
1416    conf = ptr->data;
1417
1418    if (conf->name == NULL)
1419      continue;
1420    aconf = map_to_conf(conf);
1421    if (aconf->host == NULL)
1422      continue;
1423    if (irccmp(conf->name, name) != 0)
1424      continue;
1425
1426    /*
1427    ** Accept if the *real* hostname (usually sockethost)
1428    ** socket host) matches *either* host or name field
1429    ** of the configuration.
1430    */
1431    if (!match(aconf->host, host) || !match(aconf->user, user))
1432      continue;
1433    if (type == OPER_TYPE)
1434    {
1435      struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1436
1437      if (aconf->clients >= aclass->max_total)
1438        continue;
1439    }
1440
1441    return conf;
1442  }
1443
1444  return NULL;
1445 }
1446
504   /* find_conf_name()
505   *
506   * inputs       - pointer to conf link list to search
# Line 1453 | Line 510 | find_conf_exact(ConfType type, const cha
510   * side effects - find a conf entry which matches the name
511   *                and has the given mask.
512   */
513 < struct ConfItem *
514 < find_conf_name(dlink_list *list, const char *name, ConfType type)
513 > struct MaskItem *
514 > find_conf_name(dlink_list *list, const char *name, enum maskitem_type type)
515   {
516    dlink_node *ptr;
517 <  struct ConfItem* conf;
517 >  struct MaskItem* conf;
518  
519    DLINK_FOREACH(ptr, list->head)
520    {
521      conf = ptr->data;
522 <    
522 >
523      if (conf->type == type)
524      {
525 <      if (conf->name && (irccmp(conf->name, name) == 0 ||
526 <                         match(conf->name, name)))
1470 <      return conf;
525 >      if (conf->name && !irccmp(conf->name, name))
526 >        return conf;
527      }
528    }
529  
# Line 1481 | Line 537 | find_conf_name(dlink_list *list, const c
537   * side effects - none
538   */
539   static dlink_list *
540 < map_to_list(ConfType type)
540 > map_to_list(enum maskitem_type type)
541   {
542    switch(type)
543    {
544 <  case RXLINE_TYPE:
1489 <    return(&rxconf_items);
1490 <    break;
1491 <  case XLINE_TYPE:
544 >  case CONF_XLINE:
545      return(&xconf_items);
546      break;
547 <  case ULINE_TYPE:
547 >  case CONF_ULINE:
548      return(&uconf_items);
549      break;
550 <  case NRESV_TYPE:
550 >  case CONF_NRESV:
551      return(&nresv_items);
552      break;
553 <  case OPER_TYPE:
553 >  case CONF_CRESV:
554 >    return(&cresv_items);
555 >  case CONF_OPER:
556      return(&oconf_items);
557      break;
558 <  case CLASS_TYPE:
1504 <    return(&class_items);
1505 <    break;
1506 <  case SERVER_TYPE:
558 >  case CONF_SERVER:
559      return(&server_items);
560      break;
561 <  case SERVICE_TYPE:
561 >  case CONF_SERVICE:
562      return(&service_items);
563      break;
564 <  case CLUSTER_TYPE:
564 >  case CONF_CLUSTER:
565      return(&cluster_items);
566      break;
1515  case CONF_TYPE:
1516  case GLINE_TYPE:
1517  case KLINE_TYPE:
1518  case DLINE_TYPE:
1519  case CRESV_TYPE:
567    default:
568      return NULL;
569    }
# Line 1528 | Line 575 | map_to_list(ConfType type)
575   *              - pointer to name string to find
576   *              - pointer to user
577   *              - pointer to host
578 < *              - optional action to match on as well
579 < * output       - NULL or pointer to found struct MatchItem
578 > *              - optional flags to match on as well
579 > * output       - NULL or pointer to found struct MaskItem
580   * side effects - looks for a match on name field
581   */
582 < struct ConfItem *
583 < find_matching_name_conf(ConfType type, const char *name, const char *user,
584 <                        const char *host, int action)
582 > struct MaskItem *
583 > find_matching_name_conf(enum maskitem_type type, const char *name, const char *user,
584 >                        const char *host, unsigned int flags)
585   {
586    dlink_node *ptr=NULL;
587 <  struct ConfItem *conf=NULL;
1541 <  struct AccessItem *aconf=NULL;
1542 <  struct MatchItem *match_item=NULL;
587 >  struct MaskItem *conf=NULL;
588    dlink_list *list_p = map_to_list(type);
589  
590    switch (type)
591    {
592 < #ifdef HAVE_LIBPCRE
1548 <  case RXLINE_TYPE:
1549 <      DLINK_FOREACH(ptr, list_p->head)
1550 <      {
1551 <        conf = ptr->data;
1552 <        assert(conf->regexpname);
1553 <
1554 <        if (!ircd_pcre_exec(conf->regexpname, name))
1555 <          return conf;
1556 <      }
1557 <      break;
1558 < #endif
1559 <  case SERVICE_TYPE:
592 >  case CONF_SERVICE:
593      DLINK_FOREACH(ptr, list_p->head)
594      {
595        conf = ptr->data;
# Line 1568 | Line 601 | find_matching_name_conf(ConfType type, c
601      }
602      break;
603  
604 <  case XLINE_TYPE:
605 <  case ULINE_TYPE:
606 <  case NRESV_TYPE:
604 >  case CONF_XLINE:
605 >  case CONF_ULINE:
606 >  case CONF_NRESV:
607 >  case CONF_CRESV:
608      DLINK_FOREACH(ptr, list_p->head)
609      {
610        conf = ptr->data;
611  
1578      match_item = map_to_conf(conf);
612        if (EmptyString(conf->name))
613 <        continue;
614 <      if ((name != NULL) && match_esc(conf->name, name))
613 >        continue;
614 >      if ((name != NULL) && !match(conf->name, name))
615        {
616 <        if ((user == NULL && (host == NULL)))
617 <          return conf;
618 <        if ((match_item->action & action) != action)
616 >        if ((user == NULL && (host == NULL)))
617 >          return conf;
618 >        if ((conf->flags & flags) != flags)
619            continue;
620 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
621 <          return conf;
622 <        if (match(match_item->user, user) && match(match_item->host, host))
623 <          return conf;
620 >        if (EmptyString(conf->user) || EmptyString(conf->host))
621 >          return conf;
622 >        if (!match(conf->user, user) && !match(conf->host, host))
623 >          return conf;
624        }
625      }
626        break;
627  
628 <  case SERVER_TYPE:
628 >  case CONF_SERVER:
629      DLINK_FOREACH(ptr, list_p->head)
630      {
631        conf = ptr->data;
1599      aconf = map_to_conf(conf);
632  
633 <      if ((name != NULL) && match_esc(name, conf->name))
633 >      if ((name != NULL) && !match(name, conf->name))
634          return conf;
635 <      else if ((host != NULL) && match_esc(host, aconf->host))
635 >      else if ((host != NULL) && !match(host, conf->host))
636          return conf;
637      }
638      break;
639 <  
639 >
640    default:
641      break;
642    }
# Line 1617 | Line 649 | find_matching_name_conf(ConfType type, c
649   *              - pointer to name string to find
650   *              - pointer to user
651   *              - pointer to host
652 < * output       - NULL or pointer to found struct MatchItem
652 > * output       - NULL or pointer to found struct MaskItem
653   * side effects - looks for an exact match on name field
654   */
655 < struct ConfItem *
656 < find_exact_name_conf(ConfType type, const struct Client *who, const char *name,
655 > struct MaskItem *
656 > find_exact_name_conf(enum maskitem_type type, const struct Client *who, const char *name,
657                       const char *user, const char *host)
658   {
659    dlink_node *ptr = NULL;
660 <  struct AccessItem *aconf;
661 <  struct ConfItem *conf;
1630 <  struct MatchItem *match_item;
1631 <  dlink_list *list_p;
1632 <
1633 <  list_p = map_to_list(type);
660 >  struct MaskItem *conf;
661 >  dlink_list *list_p = map_to_list(type);
662  
663    switch(type)
664    {
665 <  case RXLINE_TYPE:
666 <  case XLINE_TYPE:
667 <  case ULINE_TYPE:
668 <  case NRESV_TYPE:
665 >  case CONF_XLINE:
666 >  case CONF_ULINE:
667 >  case CONF_NRESV:
668 >  case CONF_CRESV:
669  
670      DLINK_FOREACH(ptr, list_p->head)
671      {
672        conf = ptr->data;
673 <      match_item = (struct MatchItem *)map_to_conf(conf);
673 >
674        if (EmptyString(conf->name))
675 <        continue;
676 <    
675 >        continue;
676 >
677        if (irccmp(conf->name, name) == 0)
678        {
679 <        if ((user == NULL && (host == NULL)))
680 <          return (conf);
681 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
682 <          return (conf);
683 <        if (match(match_item->user, user) && match(match_item->host, host))
684 <          return (conf);
679 >        if ((user == NULL && (host == NULL)))
680 >          return conf;
681 >        if (EmptyString(conf->user) || EmptyString(conf->host))
682 >          return conf;
683 >        if (!match(conf->user, user) && !match(conf->host, host))
684 >          return conf;
685        }
686      }
687      break;
688  
689 <  case OPER_TYPE:
689 >  case CONF_OPER:
690      DLINK_FOREACH(ptr, list_p->head)
691      {
692        conf = ptr->data;
1665      aconf = map_to_conf(conf);
693  
694        if (EmptyString(conf->name))
695          continue;
# Line 1671 | Line 698 | find_exact_name_conf(ConfType type, cons
698        {
699          if (!who)
700            return conf;
701 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
702 <          return conf;
703 <        if (match(aconf->user, who->username))
701 >        if (EmptyString(conf->user) || EmptyString(conf->host))
702 >          return NULL;
703 >        if (!match(conf->user, who->username))
704          {
705 <          switch (aconf->type)
705 >          switch (conf->htype)
706            {
707              case HM_HOST:
708 <              if (match(aconf->host, who->host) || match(aconf->host, who->sockhost))
709 <                return conf;
708 >              if (!match(conf->host, who->host) || !match(conf->host, who->sockhost))
709 >                if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
710 >                  return conf;
711                break;
712              case HM_IPV4:
713 <              if (who->localClient->aftype == AF_INET)
714 <                if (match_ipv4(&who->localClient->ip, &aconf->addr, aconf->bits))
715 <                  return conf;
713 >              if (who->connection->aftype == AF_INET)
714 >                if (match_ipv4(&who->connection->ip, &conf->addr, conf->bits))
715 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
716 >                    return conf;
717                break;
1689 #ifdef IPV6
718              case HM_IPV6:
719 <              if (who->localClient->aftype == AF_INET6)
720 <                if (match_ipv6(&who->localClient->ip, &aconf->addr, aconf->bits))
721 <                  return conf;
719 >              if (who->connection->aftype == AF_INET6)
720 >                if (match_ipv6(&who->connection->ip, &conf->addr, conf->bits))
721 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
722 >                    return conf;
723                break;
1695 #endif
724              default:
725                assert(0);
726            }
# Line 1702 | Line 730 | find_exact_name_conf(ConfType type, cons
730  
731      break;
732  
733 <  case SERVER_TYPE:
733 >  case CONF_SERVER:
734      DLINK_FOREACH(ptr, list_p->head)
735      {
736        conf = ptr->data;
737 <      aconf = (struct AccessItem *)map_to_conf(conf);
737 >
738        if (EmptyString(conf->name))
739 <        continue;
740 <    
739 >        continue;
740 >
741        if (name == NULL)
742        {
743 <        if (EmptyString(aconf->host))
744 <          continue;
745 <        if (irccmp(aconf->host, host) == 0)
746 <          return(conf);
743 >        if (EmptyString(conf->host))
744 >          continue;
745 >        if (irccmp(conf->host, host) == 0)
746 >          return conf;
747        }
748        else if (irccmp(conf->name, name) == 0)
749 <      {
1722 <          return (conf);
1723 <      }
749 >        return conf;
750      }
1725    break;
751  
1727  case CLASS_TYPE:
1728    DLINK_FOREACH(ptr, list_p->head)
1729    {
1730      conf = ptr->data;
1731      if (EmptyString(conf->name))
1732        continue;
1733    
1734      if (irccmp(conf->name, name) == 0)
1735        return (conf);
1736    }
752      break;
753  
754    default:
755      break;
756    }
757 <  return(NULL);
757 >
758 >  return NULL;
759   }
760  
761   /* rehash()
# Line 1751 | Line 767 | find_exact_name_conf(ConfType type, cons
767   int
768   rehash(int sig)
769   {
770 <  if (sig != 0)
771 <    sendto_realops_flags(UMODE_ALL, L_ALL,
772 <                         "Got signal SIGHUP, reloading ircd.conf file");
770 >  if (sig)
771 >    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
772 >                         "Got signal SIGHUP, reloading configuration file(s)");
773  
774    restart_resolver();
775  
776    /* don't close listeners until we know we can go ahead with the rehash */
777  
1762  /* Check to see if we magically got(or lost) IPv6 support */
1763  check_can_use_v6();
1764
778    read_conf_files(0);
779  
1767  if (ServerInfo.description != NULL)
1768    strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1769
780    load_conf_modules();
781 +  check_conf_klines();
782  
783 <  flush_deleted_I_P();
1773 <
1774 <  rehashed_klines = 1;
1775 < /* XXX */
1776 <  if (ConfigLoggingEntry.use_logging)
1777 <    log_close_all();
1778 <
1779 <  return(0);
783 >  return 0;
784   }
785  
786   /* set_default_conf()
# Line 1794 | Line 798 | set_default_conf(void)
798    /* verify init_class() ran, this should be an unnecessary check
799     * but its not much work.
800     */
801 <  assert(class_default == (struct ConfItem *) class_items.tail->data);
801 >  assert(class_default == class_get_list()->tail->data);
802  
803   #ifdef HAVE_LIBCRYPTO
804 <  ServerInfo.rsa_private_key = NULL;
805 <  ServerInfo.rsa_private_key_file = NULL;
804 > #if OPENSSL_VERSION_NUMBER >= 0x009080FFL && !defined(OPENSSL_NO_ECDH)
805 >  {
806 >    EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
807 >
808 >    if (key)
809 >    {
810 >      SSL_CTX_set_tmp_ecdh(ConfigServerInfo.server_ctx, key);
811 >      EC_KEY_free(key);
812 >    }
813 >  }
814 >
815 >  SSL_CTX_set_options(ConfigServerInfo.server_ctx, SSL_OP_SINGLE_ECDH_USE);
816 > #endif
817 >
818 >  ConfigServerInfo.message_digest_algorithm = EVP_sha256();
819 >  ConfigServerInfo.rsa_private_key = NULL;
820 >  ConfigServerInfo.rsa_private_key_file = NULL;
821   #endif
822  
823 <  /* ServerInfo.name is not rehashable */
824 <  /* ServerInfo.name = ServerInfo.name; */
825 <  ServerInfo.description = NULL;
826 <  DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
827 <  DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
828 <
829 <  memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
830 <  ServerInfo.specific_ipv4_vhost = 0;
831 <  memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
832 <  ServerInfo.specific_ipv6_vhost = 0;
833 <
834 <  ServerInfo.max_clients = MAXCLIENTS_MAX;
835 <
836 <  ServerInfo.hub = 0;
837 <  ServerInfo.dns_host.sin_addr.s_addr = 0;
838 <  ServerInfo.dns_host.sin_port = 0;
839 <  AdminInfo.name = NULL;
840 <  AdminInfo.email = NULL;
841 <  AdminInfo.description = NULL;
823 >  /* ConfigServerInfo.name is not rehashable */
824 >  /* ConfigServerInfo.name = ConfigServerInfo.name; */
825 >  ConfigServerInfo.description = NULL;
826 >  ConfigServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
827 >  ConfigServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
828 >
829 >  memset(&ConfigServerInfo.ip, 0, sizeof(ConfigServerInfo.ip));
830 >  ConfigServerInfo.specific_ipv4_vhost = 0;
831 >  memset(&ConfigServerInfo.ip6, 0, sizeof(ConfigServerInfo.ip6));
832 >  ConfigServerInfo.specific_ipv6_vhost = 0;
833 >
834 >  ConfigServerInfo.max_clients = MAXCLIENTS_MAX;
835 >  ConfigServerInfo.max_nick_length = 9;
836 >  ConfigServerInfo.max_topic_length = 80;
837 >  ConfigServerInfo.hub = 0;
838 >
839 >  ConfigAdminInfo.name = NULL;
840 >  ConfigAdminInfo.email = NULL;
841 >  ConfigAdminInfo.description = NULL;
842  
843 <  log_close_all();
843 >  log_del_all();
844  
845 <  ConfigLoggingEntry.use_logging = 1;
845 >  ConfigLog.use_logging = 1;
846  
847    ConfigChannel.disable_fake_channels = 0;
848 <  ConfigChannel.restrict_channels = 0;
849 <  ConfigChannel.disable_local_channels = 0;
850 <  ConfigChannel.use_invex = 1;
851 <  ConfigChannel.use_except = 1;
1833 <  ConfigChannel.use_knock = 1;
1834 <  ConfigChannel.knock_delay = 300;
848 >  ConfigChannel.invite_client_count = 10;
849 >  ConfigChannel.invite_client_time = 300;
850 >  ConfigChannel.knock_client_count = 1;
851 >  ConfigChannel.knock_client_time = 300;
852    ConfigChannel.knock_delay_channel = 60;
853 <  ConfigChannel.max_chans_per_user = 15;
1837 <  ConfigChannel.quiet_on_ban = 1;
853 >  ConfigChannel.max_channels = 25;
854    ConfigChannel.max_bans = 25;
855    ConfigChannel.default_split_user_count = 0;
856    ConfigChannel.default_split_server_count = 0;
857    ConfigChannel.no_join_on_split = 0;
858    ConfigChannel.no_create_on_split = 0;
1843  ConfigChannel.burst_topicwho = 1;
859  
860    ConfigServerHide.flatten_links = 0;
861    ConfigServerHide.links_delay = 300;
862    ConfigServerHide.hidden = 0;
1848  ConfigServerHide.disable_hidden = 0;
863    ConfigServerHide.hide_servers = 0;
864 <  DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
864 >  ConfigServerHide.hide_services = 0;
865 >  ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
866    ConfigServerHide.hide_server_ips = 0;
867 +  ConfigServerHide.disable_remote_commands = 0;
868  
869 <  
870 <  DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
871 <  ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
872 <  ConfigFileEntry.gline_min_cidr = 16;
873 <  ConfigFileEntry.gline_min_cidr6 = 48;
874 <  ConfigFileEntry.invisible_on_connect = 1;
875 <  ConfigFileEntry.burst_away = 0;
876 <  ConfigFileEntry.use_whois_actually = 1;
877 <  ConfigFileEntry.tkline_expire_notices = 1;
878 <  ConfigFileEntry.hide_spoof_ips = 1;
879 <  ConfigFileEntry.ignore_bogus_ts = 0;
880 <  ConfigFileEntry.disable_auth = 0;
881 <  ConfigFileEntry.disable_remote = 0;
882 <  ConfigFileEntry.kill_chase_time_limit = 90;
883 <  ConfigFileEntry.default_floodcount = 8;
884 <  ConfigFileEntry.failed_oper_notice = 1;
885 <  ConfigFileEntry.dots_in_ident = 0;
886 <  ConfigFileEntry.min_nonwildcard = 4;
887 <  ConfigFileEntry.min_nonwildcard_simple = 3;
888 <  ConfigFileEntry.max_accept = 20;
889 <  ConfigFileEntry.anti_nick_flood = 0;
890 <  ConfigFileEntry.max_nick_time = 20;
891 <  ConfigFileEntry.max_nick_changes = 5;
892 <  ConfigFileEntry.anti_spam_exit_message_time = 0;
893 <  ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
894 <  ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
895 <  ConfigFileEntry.kline_with_reason = 1;
896 <  ConfigFileEntry.kline_reason = NULL;
897 <  ConfigFileEntry.warn_no_nline = 1;
898 <  ConfigFileEntry.stats_o_oper_only = 0;
899 <  ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
900 <  ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
901 <  ConfigFileEntry.stats_P_oper_only = 0;
902 <  ConfigFileEntry.caller_id_wait = 60;
903 <  ConfigFileEntry.opers_bypass_callerid = 0;
904 <  ConfigFileEntry.pace_wait = 10;
905 <  ConfigFileEntry.pace_wait_simple = 1;
906 <  ConfigFileEntry.short_motd = 0;
907 <  ConfigFileEntry.ping_cookie = 0;
908 <  ConfigFileEntry.no_oper_flood = 0;
909 <  ConfigFileEntry.true_no_oper_flood = 0;
910 <  ConfigFileEntry.oper_pass_resv = 1;
911 <  ConfigFileEntry.glines = 0;
912 <  ConfigFileEntry.gline_time = 12 * 3600;
913 <  ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
914 <  ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
915 <  ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
916 <  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1901 <    UMODE_OPERWALL | UMODE_WALLOP;
1902 <  ConfigFileEntry.use_egd = 0;
1903 <  ConfigFileEntry.egdpool_path = NULL;
1904 <  ConfigFileEntry.throttle_time = 10;
869 >  ConfigGeneral.away_count = 2;
870 >  ConfigGeneral.away_time = 10;
871 >  ConfigGeneral.max_watch = WATCHSIZE_DEFAULT;
872 >  ConfigGeneral.cycle_on_host_change = 1;
873 >  ConfigGeneral.glines = 0;
874 >  ConfigGeneral.gline_time = 12 * 3600;
875 >  ConfigGeneral.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
876 >  ConfigGeneral.gline_min_cidr = 16;
877 >  ConfigGeneral.gline_min_cidr6 = 48;
878 >  ConfigGeneral.invisible_on_connect = 1;
879 >  ConfigGeneral.tkline_expire_notices = 1;
880 >  ConfigGeneral.hide_spoof_ips = 1;
881 >  ConfigGeneral.ignore_bogus_ts = 0;
882 >  ConfigGeneral.disable_auth = 0;
883 >  ConfigGeneral.kill_chase_time_limit = 90;
884 >  ConfigGeneral.default_floodcount = 8;
885 >  ConfigGeneral.failed_oper_notice = 1;
886 >  ConfigGeneral.dots_in_ident = 0;
887 >  ConfigGeneral.min_nonwildcard = 4;
888 >  ConfigGeneral.min_nonwildcard_simple = 3;
889 >  ConfigGeneral.max_accept = 20;
890 >  ConfigGeneral.anti_nick_flood = 0;
891 >  ConfigGeneral.max_nick_time = 20;
892 >  ConfigGeneral.max_nick_changes = 5;
893 >  ConfigGeneral.anti_spam_exit_message_time = 0;
894 >  ConfigGeneral.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
895 >  ConfigGeneral.ts_max_delta = TS_MAX_DELTA_DEFAULT;
896 >  ConfigGeneral.warn_no_connect_block = 1;
897 >  ConfigGeneral.stats_e_disabled = 0;
898 >  ConfigGeneral.stats_o_oper_only = 0;
899 >  ConfigGeneral.stats_k_oper_only = 1;  /* 1 = masked */
900 >  ConfigGeneral.stats_i_oper_only = 1;  /* 1 = masked */
901 >  ConfigGeneral.stats_P_oper_only = 0;
902 >  ConfigGeneral.stats_u_oper_only = 0;
903 >  ConfigGeneral.caller_id_wait = 60;
904 >  ConfigGeneral.opers_bypass_callerid = 0;
905 >  ConfigGeneral.pace_wait = 10;
906 >  ConfigGeneral.pace_wait_simple = 1;
907 >  ConfigGeneral.short_motd = 0;
908 >  ConfigGeneral.ping_cookie = 0;
909 >  ConfigGeneral.no_oper_flood = 0;
910 >  ConfigGeneral.true_no_oper_flood = 0;
911 >  ConfigGeneral.oper_pass_resv = 1;
912 >  ConfigGeneral.max_targets = MAX_TARGETS_DEFAULT;
913 >  ConfigGeneral.oper_only_umodes = UMODE_DEBUG;
914 >  ConfigGeneral.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE | UMODE_WALLOP;
915 >  ConfigGeneral.throttle_count = 1;
916 >  ConfigGeneral.throttle_time = 1;
917   }
918  
919   static void
920   validate_conf(void)
921   {
922 <  if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
923 <    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1912 <
1913 <  if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1914 <    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
922 >  if (ConfigGeneral.ts_warn_delta < TS_WARN_DELTA_MIN)
923 >    ConfigGeneral.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
924  
925 <  if (ServerInfo.network_name == NULL)
926 <    DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
925 >  if (ConfigGeneral.ts_max_delta < TS_MAX_DELTA_MIN)
926 >    ConfigGeneral.ts_max_delta = TS_MAX_DELTA_DEFAULT;
927  
928 <  if (ServerInfo.network_desc == NULL)
929 <    DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
928 >  if (ConfigServerInfo.network_name == NULL)
929 >    ConfigServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
930  
931 <  if (ConfigFileEntry.service_name == NULL)
932 <    DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
931 >  if (ConfigServerInfo.network_desc == NULL)
932 >    ConfigServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
933  
934 <  if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1926 <      (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1927 <    ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1928 <
1929 <  ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
934 >  ConfigGeneral.max_watch = IRCD_MAX(ConfigGeneral.max_watch, WATCHSIZE_MIN);
935   }
936  
937 < /* read_conf()
937 > /* read_conf()
938   *
939   * inputs       - file descriptor pointing to config file to use
940   * output       - None
# Line 1940 | Line 945 | read_conf(FILE *file)
945   {
946    lineno = 0;
947  
948 <  set_default_conf(); /* Set default values prior to conf parsing */
948 >  set_default_conf();  /* Set default values prior to conf parsing */
949    conf_parser_ctx.pass = 1;
950 <  yyparse();          /* pick up the classes first */
950 >  yyparse();  /* Pick up the classes first */
951  
952    rewind(file);
953  
954    conf_parser_ctx.pass = 2;
955 <  yyparse();          /* Load the values from the conf */
956 <  validate_conf();    /* Check to make sure some values are still okay. */
957 <                      /* Some global values are also loaded here. */
958 <  check_class();      /* Make sure classes are valid */
955 >  yyparse();  /* Load the values from the conf */
956 >  validate_conf();  /* Check to make sure some values are still okay. */
957 >                    /* Some global values are also loaded here. */
958 >  class_delete_marked();  /* Delete unused classes that are marked for deletion */
959   }
960  
961   /* lookup_confhost()
# Line 1958 | Line 963 | read_conf(FILE *file)
963   * start DNS lookups of all hostnames in the conf
964   * line and convert an IP addresses in a.b.c.d number for to IP#s.
965   */
966 < static void
967 < lookup_confhost(struct ConfItem *conf)
966 > void
967 > lookup_confhost(struct MaskItem *conf)
968   {
1964  struct AccessItem *aconf;
969    struct addrinfo hints, *res;
970  
971 <  aconf = map_to_conf(conf);
972 <
1969 <  if (EmptyString(aconf->host) ||
1970 <      EmptyString(aconf->user))
1971 <  {
1972 <    ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
1973 <         aconf->host, conf->name);
1974 <    return;
1975 <  }
1976 <
1977 <  if (strchr(aconf->host, '*') ||
1978 <      strchr(aconf->host, '?'))
1979 <    return;
1980 <
1981 <  /* Do name lookup now on hostnames given and store the
971 >  /*
972 >   * Do name lookup now on hostnames given and store the
973     * ip numbers in conf structure.
974     */
975    memset(&hints, 0, sizeof(hints));
# Line 1989 | Line 980 | lookup_confhost(struct ConfItem *conf)
980    /* Get us ready for a bind() and don't bother doing dns lookup */
981    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
982  
983 <  if (getaddrinfo(aconf->host, NULL, &hints, &res))
983 >  if (getaddrinfo(conf->host, NULL, &hints, &res))
984    {
985 <    conf_dns_lookup(aconf);
985 >    conf_dns_lookup(conf);
986      return;
987    }
988  
989 <  assert(res != NULL);
989 >  assert(res);
990 >
991 >  memcpy(&conf->addr, res->ai_addr, res->ai_addrlen);
992 >  conf->addr.ss_len = res->ai_addrlen;
993 >  conf->addr.ss.ss_family = res->ai_family;
994  
2000  memcpy(&aconf->addr, res->ai_addr, res->ai_addrlen);
2001  aconf->addr.ss_len = res->ai_addrlen;
2002  aconf->addr.ss.ss_family = res->ai_family;
995    freeaddrinfo(res);
996   }
997  
# Line 2013 | Line 1005 | lookup_confhost(struct ConfItem *conf)
1005   int
1006   conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1007   {
1008 <  struct ip_entry *ip_found;
1009 <  struct AccessItem *aconf = find_dline_conf(addr, aftype);
1008 >  struct ip_entry *ip_found = NULL;
1009 >  struct MaskItem *conf = find_dline_conf(addr, aftype);
1010  
1011    /* DLINE exempt also gets you out of static limits/pacing... */
1012 <  if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1012 >  if (conf && (conf->type == CONF_EXEMPT))
1013      return 0;
1014  
1015 <  if (aconf != NULL)
1015 >  if (conf)
1016      return BANNED_CLIENT;
1017  
1018 <  ip_found = find_or_add_ip(addr);
1018 >  ip_found = ipcache_find_or_add_address(addr);
1019  
1020 <  if ((CurrentTime - ip_found->last_attempt) <
2029 <      ConfigFileEntry.throttle_time)
1020 >  if ((CurrentTime - ip_found->last_attempt) < ConfigGeneral.throttle_time)
1021    {
1022 <    ip_found->last_attempt = CurrentTime;
1023 <    return TOO_FAST;
1022 >    if (ip_found->connection_count >= ConfigGeneral.throttle_count)
1023 >      return TOO_FAST;
1024 >
1025 >    ++ip_found->connection_count;
1026    }
1027 +  else
1028 +    ip_found->connection_count = 1;
1029  
1030    ip_found->last_attempt = CurrentTime;
1031    return 0;
1032   }
1033  
2039 static struct AccessItem *
2040 find_regexp_kline(const char *uhi[])
2041 {
2042 #ifdef HAVE_LIBPCRE
2043  const dlink_node *ptr = NULL;
2044
2045  DLINK_FOREACH(ptr, rkconf_items.head)
2046  {
2047    struct AccessItem *aptr = map_to_conf(ptr->data);
2048
2049    assert(aptr->regexuser);
2050    assert(aptr->regexhost);
2051
2052    if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2053        (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2054         !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2055      return aptr;
2056  }
2057 #endif
2058  return NULL;
2059 }
2060
2061 /* find_kill()
2062 *
2063 * inputs       - pointer to client structure
2064 * output       - pointer to struct AccessItem if found
2065 * side effects - See if this user is klined already,
2066 *                and if so, return struct AccessItem pointer
2067 */
2068 struct AccessItem *
2069 find_kill(struct Client *client_p)
2070 {
2071  struct AccessItem *aconf = NULL;
2072  const char *uhi[3];
2073
2074  uhi[0] = client_p->username;
2075  uhi[1] = client_p->host;
2076  uhi[2] = client_p->sockhost;
2077
2078  assert(client_p != NULL);
2079
2080  aconf = find_kline_conf(client_p->host, client_p->username,
2081                          &client_p->localClient->ip,
2082                          client_p->localClient->aftype);
2083  if (aconf == NULL)
2084    aconf = find_regexp_kline(uhi);
2085
2086  if (aconf && (aconf->status & CONF_KLINE))
2087    return aconf;
2088
2089  return NULL;
2090 }
2091
2092 struct AccessItem *
2093 find_gline(struct Client *client_p)
2094 {
2095  struct AccessItem *aconf;
2096
2097  assert(client_p != NULL);
2098
2099  aconf = find_gline_conf(client_p->host, client_p->username,
2100                          &client_p->localClient->ip,
2101                          client_p->localClient->aftype);
2102
2103  if (aconf && (aconf->status & CONF_GLINE))
2104    return aconf;
2105
2106  return NULL;
2107 }
2108
2109 /* add_temp_line()
2110 *
2111 * inputs        - pointer to struct ConfItem
2112 * output        - none
2113 * Side effects  - links in given struct ConfItem into
2114 *                 temporary *line link list
2115 */
2116 void
2117 add_temp_line(struct ConfItem *conf)
2118 {
2119  if (conf->type == XLINE_TYPE)
2120  {
2121    conf->flags |= CONF_FLAGS_TEMPORARY;
2122    dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2123  }
2124  else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2125  {
2126    conf->flags |= CONF_FLAGS_TEMPORARY;
2127    dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2128  }
2129 }
2130
1034   /* cleanup_tklines()
1035   *
1036   * inputs       - NONE
# Line 2136 | Line 1039 | add_temp_line(struct ConfItem *conf)
1039   *                This is an event started off in ircd.c
1040   */
1041   void
1042 < cleanup_tklines(void *notused)
1042 > cleanup_tklines(void *unused)
1043   {
1044    hostmask_expire_temporary();
1045 <  expire_tklines(&temporary_xlines);
1046 <  expire_tklines(&temporary_resv);
1045 >  expire_tklines(&xconf_items);
1046 >  expire_tklines(&nresv_items);
1047 >  expire_tklines(&cresv_items);
1048   }
1049  
1050   /* expire_tklines()
# Line 2152 | Line 1056 | cleanup_tklines(void *notused)
1056   static void
1057   expire_tklines(dlink_list *tklist)
1058   {
1059 <  dlink_node *ptr;
1060 <  dlink_node *next_ptr;
2157 <  struct ConfItem *conf;
2158 <  struct MatchItem *xconf;
2159 <  struct MatchItem *nconf;
2160 <  struct ResvChannel *cconf;
1059 >  dlink_node *ptr = NULL, *ptr_next = NULL;
1060 >  struct MaskItem *conf = NULL;
1061  
1062 <  DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
1062 >  DLINK_FOREACH_SAFE(ptr, ptr_next, tklist->head)
1063    {
1064      conf = ptr->data;
1065  
1066 <    if (conf->type == XLINE_TYPE)
1066 >    if (!conf->until || conf->until > CurrentTime)
1067 >      continue;
1068 >
1069 >    if (conf->type == CONF_XLINE)
1070      {
1071 <      xconf = (struct MatchItem *)map_to_conf(conf);
1072 <      if (xconf->hold <= CurrentTime)
1073 <      {
1074 <        if (ConfigFileEntry.tkline_expire_notices)
2172 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2173 <                               "Temporary X-line for [%s] sexpired", conf->name);
2174 <        dlinkDelete(ptr, tklist);
2175 <        free_dlink_node(ptr);
2176 <        delete_conf_item(conf);
2177 <      }
1071 >      if (ConfigGeneral.tkline_expire_notices)
1072 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1073 >                               "Temporary X-line for [%s] expired", conf->name);
1074 >      conf_free(conf);
1075      }
1076 <    else if (conf->type == NRESV_TYPE)
1076 >    else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1077      {
1078 <      nconf = (struct MatchItem *)map_to_conf(conf);
1079 <      if (nconf->hold <= CurrentTime)
2183 <      {
2184 <        if (ConfigFileEntry.tkline_expire_notices)
2185 <          sendto_realops_flags(UMODE_ALL, L_ALL,
1078 >      if (ConfigGeneral.tkline_expire_notices)
1079 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1080                                 "Temporary RESV for [%s] expired", conf->name);
1081 <        dlinkDelete(ptr, tklist);
2188 <        free_dlink_node(ptr);
2189 <        delete_conf_item(conf);
2190 <      }
2191 <    }
2192 <    else if (conf->type == CRESV_TYPE)
2193 <    {
2194 <      cconf = (struct ResvChannel *)map_to_conf(conf);
2195 <      if (cconf->hold <= CurrentTime)
2196 <      {
2197 <        if (ConfigFileEntry.tkline_expire_notices)
2198 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2199 <                               "Temporary RESV for [%s] expired", cconf->name);
2200 <        delete_channel_resv(cconf);
2201 <      }
1081 >      conf_free(conf);
1082      }
1083    }
1084   }
# Line 2211 | Line 1091 | expire_tklines(dlink_list *tklist)
1091   */
1092   static const struct oper_privs
1093   {
1094 <  const unsigned int oprivs;
1094 >  const unsigned int flag;
1095    const unsigned char c;
1096   } flag_list[] = {
1097 <  { OPER_FLAG_ADMIN,       'A' },
1098 <  { OPER_FLAG_REMOTEBAN,   'B' },
1099 <  { OPER_FLAG_DIE,         'D' },
1100 <  { OPER_FLAG_GLINE,       'G' },
1101 <  { OPER_FLAG_REHASH,      'H' },
1102 <  { OPER_FLAG_K,           'K' },
1103 <  { OPER_FLAG_OPERWALL,    'L' },
1104 <  { OPER_FLAG_N,           'N' },
1105 <  { OPER_FLAG_GLOBAL_KILL, 'O' },
1106 <  { OPER_FLAG_REMOTE,      'R' },
1107 <  { OPER_FLAG_OPER_SPY,    'S' },
1108 <  { OPER_FLAG_UNKLINE,     'U' },
1109 <  { OPER_FLAG_X,           'X' },
1097 >  { OPER_FLAG_ADMIN,          'A' },
1098 >  { OPER_FLAG_REMOTEBAN,      'B' },
1099 >  { OPER_FLAG_DIE,            'D' },
1100 >  { OPER_FLAG_GLINE,          'G' },
1101 >  { OPER_FLAG_REHASH,         'H' },
1102 >  { OPER_FLAG_KLINE,          'K' },
1103 >  { OPER_FLAG_KILL,           'N' },
1104 >  { OPER_FLAG_KILL_REMOTE,    'O' },
1105 >  { OPER_FLAG_CONNECT,        'P' },
1106 >  { OPER_FLAG_CONNECT_REMOTE, 'Q' },
1107 >  { OPER_FLAG_SQUIT,          'R' },
1108 >  { OPER_FLAG_SQUIT_REMOTE,   'S' },
1109 >  { OPER_FLAG_UNKLINE,        'U' },
1110 >  { OPER_FLAG_XLINE,          'X' },
1111    { 0, '\0' }
1112   };
1113  
1114   char *
1115   oper_privs_as_string(const unsigned int port)
1116   {
1117 <  static char privs_out[16];
1117 >  static char privs_out[IRCD_BUFSIZE];
1118    char *privs_ptr = privs_out;
2238  unsigned int i = 0;
1119  
1120 <  for (; flag_list[i].oprivs; ++i)
1120 >  for (const struct oper_privs *opriv = flag_list; opriv->flag; ++opriv)
1121    {
1122 <    if (port & flag_list[i].oprivs)
1123 <      *privs_ptr++ = flag_list[i].c;
1122 >    if (port & opriv->flag)
1123 >      *privs_ptr++ = opriv->c;
1124      else
1125 <      *privs_ptr++ = ToLowerTab[flag_list[i].c];
1125 >      *privs_ptr++ = ToLower(opriv->c);
1126    }
1127  
1128    *privs_ptr = '\0';
# Line 2251 | Line 1131 | oper_privs_as_string(const unsigned int
1131   }
1132  
1133   /*
1134 < * Input: A client to find the active oper{} name for.
1134 > * Input: A client to find the active operator {} name for.
1135   * Output: The nick!user@host{oper} of the oper.
1136   *         "oper" is server name for remote opers
1137   * Side effects: None.
# Line 2259 | Line 1139 | oper_privs_as_string(const unsigned int
1139   const char *
1140   get_oper_name(const struct Client *client_p)
1141   {
1142 <  dlink_node *cnode = NULL;
1142 >  const dlink_node *cnode = NULL;
1143    /* +5 for !,@,{,} and null */
1144    static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
1145  
1146 +  if (IsServer(client_p))
1147 +    return client_p->name;
1148 +
1149    if (MyConnect(client_p))
1150    {
1151 <    if ((cnode = client_p->localClient->confs.head))
1151 >    if ((cnode = client_p->connection->confs.head))
1152      {
1153 <      struct ConfItem *conf = cnode->data;
2271 <      const struct AccessItem *aconf = map_to_conf(conf);
1153 >      const struct MaskItem *conf = cnode->data;
1154  
1155 <      if (IsConfOperator(aconf))
1155 >      if (IsConfOperator(conf))
1156        {
1157 <        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1157 >        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1158                   client_p->username, client_p->host, conf->name);
1159 <        return buffer;
1159 >        return buffer;
1160        }
1161      }
1162  
1163 <    /* Probably should assert here for now. If there is an oper out there
1164 <     * with no oper{} conf attached, it would be good for us to know...
1163 >    /*
1164 >     * Probably should assert here for now. If there is an oper out there
1165 >     * with no operator {} conf attached, it would be good for us to know...
1166       */
1167 <    assert(0); /* Oper without oper conf! */
1167 >    assert(0);  /* Oper without oper conf! */
1168    }
1169  
1170    snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1171 <           client_p->username, client_p->host, client_p->servptr->name);
1171 >           client_p->username, client_p->host, client_p->servptr->name);
1172    return buffer;
1173   }
1174  
# Line 2298 | Line 1181 | get_oper_name(const struct Client *clien
1181   void
1182   read_conf_files(int cold)
1183   {
1184 <  const char *filename;
1185 <  char chanmodes[32];
1186 <  char chanlimit[32];
1184 >  const char *filename = NULL;
1185 >  char chanmodes[IRCD_BUFSIZE] = "";
1186 >  char chanlimit[IRCD_BUFSIZE] = "";
1187  
1188    conf_parser_ctx.boot = cold;
1189 <  filename = get_conf_name(CONF_TYPE);
1189 >  filename = ConfigGeneral.configfile;
1190  
1191    /* We need to know the initial filename for the yyerror() to report
1192       FIXME: The full path is in conffilenamebuf first time since we
1193 <             dont know anything else
1193 >             don't know anything else
1194  
1195 <     - Gozem 2002-07-21
1195 >     - Gozem 2002-07-21
1196    */
1197    strlcpy(conffilebuf, filename, sizeof(conffilebuf));
1198  
# Line 2323 | Line 1206 | read_conf_files(int cold)
1206      }
1207      else
1208      {
1209 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1210 <                           "Unable to read configuration file '%s': %s",
1211 <                           filename, strerror(errno));
1209 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1210 >                           "Unable to read configuration file '%s': %s",
1211 >                           filename, strerror(errno));
1212        return;
1213      }
1214    }
# Line 2336 | Line 1219 | read_conf_files(int cold)
1219    read_conf(conf_parser_ctx.conf_file);
1220    fclose(conf_parser_ctx.conf_file);
1221  
1222 <  add_isupport("NETWORK", ServerInfo.network_name, -1);
2340 <  snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
2341 <           ConfigChannel.use_except ? "e" : "",
2342 <           ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
2343 <  add_isupport("MAXLIST", chanmodes, -1);
2344 <  add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1222 >  log_reopen_all();
1223  
1224 <  if (ConfigChannel.disable_local_channels)
1225 <    add_isupport("CHANTYPES", "#", -1);
2348 <  else
2349 <    add_isupport("CHANTYPES", "#&", -1);
1224 >  add_isupport("NICKLEN", NULL, ConfigServerInfo.max_nick_length);
1225 >  add_isupport("NETWORK", ConfigServerInfo.network_name, -1);
1226  
1227 <  snprintf(chanlimit, sizeof(chanlimit), "%s:%d",
1228 <           ConfigChannel.disable_local_channels ? "#" : "#&",
1229 <           ConfigChannel.max_chans_per_user);
1227 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1228 >  add_isupport("MAXLIST", chanmodes, -1);
1229 >  add_isupport("MAXTARGETS", NULL, ConfigGeneral.max_targets);
1230 >  add_isupport("CHANTYPES", "#", -1);
1231 >
1232 >  snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1233 >           ConfigChannel.max_channels);
1234    add_isupport("CHANLIMIT", chanlimit, -1);
1235 <  snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
1236 <           ConfigChannel.use_except ? "e" : "",
1237 <           ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
2358 <  add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2359 <
2360 <  if (ConfigChannel.use_except)
2361 <    add_isupport("EXCEPTS", "e", -1);
2362 <  if (ConfigChannel.use_invex)
2363 <    add_isupport("INVEX", "I", -1);
1235 >  snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,cimnprstMORS");
1236 >  add_isupport("CHANNELLEN", NULL, CHANNELLEN);
1237 >  add_isupport("TOPICLEN", NULL, ConfigServerInfo.max_topic_length);
1238    add_isupport("CHANMODES", chanmodes, -1);
1239  
1240    /*
# Line 2368 | Line 1242 | read_conf_files(int cold)
1242     * on strlen(form_str(RPL_ISUPPORT))
1243     */
1244    rebuild_isupport_message_line();
2371
2372 #ifdef HAVE_LIBPCRE
2373  parse_conf_file(RKLINE_TYPE, cold);
2374  parse_conf_file(RXLINE_TYPE, cold);
2375 #endif
2376  parse_conf_file(KLINE_TYPE, cold);
2377  parse_conf_file(DLINE_TYPE, cold);
2378  parse_conf_file(XLINE_TYPE, cold);
2379  parse_conf_file(NRESV_TYPE, cold);
2380  parse_conf_file(CRESV_TYPE, cold);
2381 }
2382
2383 /* parse_conf_file()
2384 *
2385 * inputs       - type of conf file to parse
2386 * output       - none
2387 * side effects - conf file for givenconf type is opened and read then parsed
2388 */
2389 static void
2390 parse_conf_file(int type, int cold)
2391 {
2392  FILE *file = NULL;
2393  const char *filename = get_conf_name(type);
2394
2395  if ((file = fopen(filename, "r")) == NULL)
2396  {
2397    if (cold)
2398      ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2399           filename, strerror(errno));
2400    else
2401      sendto_realops_flags(UMODE_ALL, L_ALL,
2402                    "Unable to read configuration file '%s': %s",
2403                           filename, strerror(errno));
2404  }
2405  else
2406  {
2407    parse_csv_file(file, type);
2408    fclose(file);
2409  }
1245   }
1246  
1247   /* clear_out_old_conf()
# Line 2419 | Line 1254 | static void
1254   clear_out_old_conf(void)
1255   {
1256    dlink_node *ptr = NULL, *next_ptr = NULL;
2422  struct ConfItem *conf;
2423  struct AccessItem *aconf;
2424  struct ClassItem *cltmp;
2425  struct MatchItem *match_item;
1257    dlink_list *free_items [] = {
1258      &server_items,   &oconf_items,
1259 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1260 <     &nresv_items, &cluster_items,  &gdeny_items, &service_items, NULL
1259 >     &uconf_items,   &xconf_items,
1260 >     &nresv_items, &cluster_items,  &service_items, &cresv_items, NULL
1261    };
1262  
1263    dlink_list ** iterator = free_items; /* C is dumb */
# Line 2434 | Line 1265 | clear_out_old_conf(void)
1265    /* We only need to free anything allocated by yyparse() here.
1266     * Resetting structs, etc, is taken care of by set_default_conf().
1267     */
1268 <  
1268 >
1269    for (; *iterator != NULL; iterator++)
1270    {
1271      DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1272      {
1273 <      conf = ptr->data;
2443 <      /* XXX This is less than pretty */
2444 <      if (conf->type == SERVER_TYPE)
2445 <      {
2446 <        aconf = map_to_conf(conf);
1273 >      struct MaskItem *conf = ptr->data;
1274  
1275 <        if (aconf->clients != 0)
1276 <        {
2450 <          SetConfIllegal(aconf);
2451 <          dlinkDelete(&conf->node, &server_items);
2452 <        }
2453 <        else
2454 <        {
2455 <          delete_conf_item(conf);
2456 <        }
2457 <      }
2458 <      else if (conf->type == OPER_TYPE)
2459 <      {
2460 <        aconf = map_to_conf(conf);
1275 >      conf->active = 0;
1276 >      dlinkDelete(&conf->node, *iterator);
1277  
1278 <        if (aconf->clients != 0)
1279 <        {
2464 <          SetConfIllegal(aconf);
2465 <          dlinkDelete(&conf->node, &oconf_items);
2466 <        }
2467 <        else
2468 <        {
2469 <          delete_conf_item(conf);
2470 <        }
2471 <      }
2472 <      else if (conf->type == XLINE_TYPE  ||
2473 <               conf->type == RXLINE_TYPE ||
2474 <               conf->type == RKLINE_TYPE)
1278 >      /* XXX This is less than pretty */
1279 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1280        {
1281 <        /* temporary (r)xlines are also on
1282 <         * the (r)xconf items list */
2478 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2479 <          continue;
2480 <
2481 <        delete_conf_item(conf);
1281 >        if (!conf->ref_count)
1282 >          conf_free(conf);
1283        }
1284 <      else
1284 >      else if (conf->type == CONF_XLINE)
1285        {
1286 <          delete_conf_item(conf);
1286 >        if (!conf->until)
1287 >          conf_free(conf);
1288        }
1289 +      else
1290 +        conf_free(conf);
1291      }
1292    }
1293  
1294 +  motd_clear();
1295 +
1296    /*
1297     * don't delete the class table, rather mark all entries
1298 <   * for deletion. The table is cleaned up by check_class. - avalon
1298 >   * for deletion. The table is cleaned up by class_delete_marked. - avalon
1299     */
1300 <  DLINK_FOREACH(ptr, class_items.head)
2495 <  {
2496 <    cltmp = map_to_conf(ptr->data);
2497 <
2498 <    if (ptr != class_items.tail)  /* never mark the "default" class */
2499 <      cltmp->active = 0;
2500 <  }
1300 >  class_mark_for_deletion();
1301  
1302    clear_out_address_conf();
1303  
1304    /* clean out module paths */
1305    mod_clear_paths();
1306  
1307 <  /* clean out ServerInfo */
1308 <  MyFree(ServerInfo.description);
1309 <  ServerInfo.description = NULL;
1310 <  MyFree(ServerInfo.network_name);
1311 <  ServerInfo.network_name = NULL;
1312 <  MyFree(ServerInfo.network_desc);
1313 <  ServerInfo.network_desc = NULL;
1314 <  MyFree(ConfigFileEntry.egdpool_path);
1315 <  ConfigFileEntry.egdpool_path = NULL;
1307 >  pseudo_clear();
1308 >
1309 >  /* clean out ConfigServerInfo */
1310 >  MyFree(ConfigServerInfo.description);
1311 >  ConfigServerInfo.description = NULL;
1312 >  MyFree(ConfigServerInfo.network_name);
1313 >  ConfigServerInfo.network_name = NULL;
1314 >  MyFree(ConfigServerInfo.network_desc);
1315 >  ConfigServerInfo.network_desc = NULL;
1316   #ifdef HAVE_LIBCRYPTO
1317 <  if (ServerInfo.rsa_private_key != NULL)
1317 >  if (ConfigServerInfo.rsa_private_key)
1318    {
1319 <    RSA_free(ServerInfo.rsa_private_key);
1320 <    ServerInfo.rsa_private_key = NULL;
1319 >    RSA_free(ConfigServerInfo.rsa_private_key);
1320 >    ConfigServerInfo.rsa_private_key = NULL;
1321    }
1322  
1323 <  MyFree(ServerInfo.rsa_private_key_file);
1324 <  ServerInfo.rsa_private_key_file = NULL;
2525 <
2526 <  if (ServerInfo.server_ctx)
2527 <    SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
2528 <                                               SSL_OP_NO_SSLv3|
2529 <                                               SSL_OP_NO_TLSv1);
2530 <  if (ServerInfo.client_ctx)
2531 <    SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
2532 <                                               SSL_OP_NO_SSLv3|
2533 <                                               SSL_OP_NO_TLSv1);
1323 >  MyFree(ConfigServerInfo.rsa_private_key_file);
1324 >  ConfigServerInfo.rsa_private_key_file = NULL;
1325   #endif
1326  
1327 <  /* clean out old resvs from the conf */
1328 <  clear_conf_resv();
1327 >  /* clean out ConfigAdminInfo */
1328 >  MyFree(ConfigAdminInfo.name);
1329 >  ConfigAdminInfo.name = NULL;
1330 >  MyFree(ConfigAdminInfo.email);
1331 >  ConfigAdminInfo.email = NULL;
1332 >  MyFree(ConfigAdminInfo.description);
1333 >  ConfigAdminInfo.description = NULL;
1334  
2539  /* clean out AdminInfo */
2540  MyFree(AdminInfo.name);
2541  AdminInfo.name = NULL;
2542  MyFree(AdminInfo.email);
2543  AdminInfo.email = NULL;
2544  MyFree(AdminInfo.description);
2545  AdminInfo.description = NULL;
2546
2547  /* operator{} and class{} blocks are freed above */
1335    /* clean out listeners */
1336    close_listeners();
2550
2551  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2552   * exempt{} and gecos{} blocks are freed above too
2553   */
2554
2555  /* clean out general */
2556  MyFree(ConfigFileEntry.service_name);
2557  ConfigFileEntry.service_name = NULL;
2558
2559  delete_isupport("INVEX");
2560  delete_isupport("EXCEPTS");
2561 }
2562
2563 /* flush_deleted_I_P()
2564 *
2565 * inputs       - none
2566 * output       - none
2567 * side effects - This function removes I/P conf items
2568 */
2569 static void
2570 flush_deleted_I_P(void)
2571 {
2572  dlink_node *ptr;
2573  dlink_node *next_ptr;
2574  struct ConfItem *conf;
2575  struct AccessItem *aconf;
2576  dlink_list * free_items [] = {
2577    &server_items, &oconf_items, NULL
2578  };
2579  dlink_list ** iterator = free_items; /* C is dumb */
2580
2581  /* flush out deleted I and P lines
2582   * although still in use.
2583   */
2584  for (; *iterator != NULL; iterator++)
2585  {
2586    DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2587    {
2588      conf = ptr->data;
2589      aconf = (struct AccessItem *)map_to_conf(conf);
2590
2591      if (IsConfIllegal(aconf))
2592      {
2593        dlinkDelete(ptr, *iterator);
2594
2595        if (aconf->clients == 0)
2596          delete_conf_item(conf);
2597      }
2598    }
2599  }
2600 }
2601
2602 /* get_conf_name()
2603 *
2604 * inputs       - type of conf file to return name of file for
2605 * output       - pointer to filename for type of conf
2606 * side effects - none
2607 */
2608 const char *
2609 get_conf_name(ConfType type)
2610 {
2611  switch (type)
2612  {
2613    case CONF_TYPE:
2614      return ConfigFileEntry.configfile;
2615      break;
2616    case KLINE_TYPE:
2617      return ConfigFileEntry.klinefile;
2618      break;
2619    case RKLINE_TYPE:
2620      return ConfigFileEntry.rklinefile;
2621      break;
2622    case DLINE_TYPE:
2623      return ConfigFileEntry.dlinefile;
2624      break;
2625    case XLINE_TYPE:
2626      return ConfigFileEntry.xlinefile;
2627      break;
2628    case RXLINE_TYPE:
2629      return ConfigFileEntry.rxlinefile;
2630      break;
2631    case CRESV_TYPE:
2632      return ConfigFileEntry.cresvfile;
2633      break;
2634    case NRESV_TYPE:
2635      return ConfigFileEntry.nresvfile;
2636      break;
2637    case GLINE_TYPE:
2638      return ConfigFileEntry.glinefile;
2639      break;
2640
2641    default:
2642      return NULL;  /* This should NEVER HAPPEN since we call this function
2643                       only with the above values, this will cause us to core
2644                       at some point if this happens so we know where it was */
2645  }
2646 }
2647
2648 #define BAD_PING (-1)
2649
2650 /* get_conf_ping()
2651 *
2652 * inputs       - pointer to struct AccessItem
2653 *              - pointer to a variable that receives ping warning time
2654 * output       - ping frequency
2655 * side effects - NONE
2656 */
2657 static int
2658 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2659 {
2660  struct ClassItem *aclass;
2661  struct AccessItem *aconf;
2662
2663  if (conf != NULL)
2664  {
2665    aconf = (struct AccessItem *)map_to_conf(conf);
2666    if (aconf->class_ptr != NULL)
2667    {
2668      aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2669      *pingwarn = aclass->ping_warning;
2670      return aclass->ping_freq;
2671    }
2672  }
2673
2674  return BAD_PING;
2675 }
2676
2677 /* get_client_class()
2678 *
2679 * inputs       - pointer to client struct
2680 * output       - pointer to name of class
2681 * side effects - NONE
2682 */
2683 const char *
2684 get_client_class(struct Client *target_p)
2685 {
2686  dlink_node *cnode = NULL;
2687  struct AccessItem *aconf = NULL;
2688
2689  assert(!IsMe(target_p));
2690
2691  if ((cnode = target_p->localClient->confs.head))
2692  {
2693    struct ConfItem *conf = cnode->data;
2694
2695    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2696          (conf->type == OPER_TYPE));
2697
2698    aconf = map_to_conf(conf);
2699    if (aconf->class_ptr != NULL)
2700      return aconf->class_ptr->name;
2701  }
2702
2703  return "default";
2704 }
2705
2706 /* get_client_ping()
2707 *
2708 * inputs       - pointer to client struct
2709 *              - pointer to a variable that receives ping warning time
2710 * output       - ping frequency
2711 * side effects - NONE
2712 */
2713 int
2714 get_client_ping(struct Client *target_p, int *pingwarn)
2715 {
2716  int ping = 0;
2717  dlink_node *cnode = NULL;
2718
2719  if ((cnode = target_p->localClient->confs.head))
2720  {
2721    struct ConfItem *conf = cnode->data;
2722
2723    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2724          (conf->type == OPER_TYPE));
2725
2726    ping = get_conf_ping(conf, pingwarn);
2727    if (ping > 0)
2728      return ping;
2729  }
2730
2731  *pingwarn = 0;
2732  return DEFAULT_PINGFREQUENCY;
2733 }
2734
2735 /* find_class()
2736 *
2737 * inputs       - string name of class
2738 * output       - corresponding Class pointer
2739 * side effects - NONE
2740 */
2741 struct ConfItem *
2742 find_class(const char *classname)
2743 {
2744  struct ConfItem *conf;
2745
2746  if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2747    return conf;
2748
2749  return class_default;
2750 }
2751
2752 /* check_class()
2753 *
2754 * inputs       - NONE
2755 * output       - NONE
2756 * side effects -
2757 */
2758 void
2759 check_class(void)
2760 {
2761  dlink_node *ptr = NULL, *next_ptr = NULL;
2762
2763  DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2764  {
2765    struct ClassItem *aclass = map_to_conf(ptr->data);
2766
2767    if (!aclass->active && !aclass->curr_user_count)
2768    {
2769      destroy_cidr_class(aclass);
2770      delete_conf_item(ptr->data);
2771    }
2772  }
2773 }
2774
2775 /* init_class()
2776 *
2777 * inputs       - NONE
2778 * output       - NONE
2779 * side effects -
2780 */
2781 void
2782 init_class(void)
2783 {
2784  struct ClassItem *aclass;
2785
2786  class_default = make_conf_item(CLASS_TYPE);
2787
2788  aclass = map_to_conf(class_default);
2789  aclass->active = 1;
2790  DupString(class_default->name, "default");
2791  aclass->con_freq  = DEFAULT_CONNECTFREQUENCY;
2792  aclass->ping_freq = DEFAULT_PINGFREQUENCY;
2793  aclass->max_total = MAXIMUM_LINKS_DEFAULT;
2794  aclass->max_sendq = DEFAULT_SENDQ;
2795
2796  client_check_cb = register_callback("check_client", check_client);
2797 }
2798
2799 /* get_sendq()
2800 *
2801 * inputs       - pointer to client
2802 * output       - sendq for this client as found from its class
2803 * side effects - NONE
2804 */
2805 unsigned int
2806 get_sendq(struct Client *client_p)
2807 {
2808  unsigned int sendq = DEFAULT_SENDQ;
2809  dlink_node *cnode;
2810  struct ConfItem *class_conf;
2811  struct ClassItem *aclass;
2812  struct AccessItem *aconf;
2813
2814  assert(!IsMe(client_p));
2815
2816  if ((cnode = client_p->localClient->confs.head))
2817  {
2818    struct ConfItem *conf = cnode->data;
2819
2820    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2821          (conf->type == OPER_TYPE));
2822
2823    aconf = map_to_conf(conf);
2824
2825    if ((class_conf = aconf->class_ptr) == NULL)
2826      return DEFAULT_SENDQ; /* TBV: shouldn't be possible at all */
2827
2828    aclass = map_to_conf(class_conf);
2829    sendq = aclass->max_sendq;
2830    return sendq;
2831  }
2832
2833  /* XXX return a default?
2834   * if here, then there wasn't an attached conf with a sendq
2835   * that is very bad -Dianora
2836   */
2837  return DEFAULT_SENDQ;
1337   }
1338  
1339   /* conf_add_class_to_conf()
1340   *
1341   * inputs       - pointer to config item
1342   * output       - NONE
1343 < * side effects - Add a class pointer to a conf
1343 > * side effects - Add a class pointer to a conf
1344   */
1345   void
1346 < conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
1346 > conf_add_class_to_conf(struct MaskItem *conf, const char *class_name)
1347   {
1348 <  struct AccessItem *aconf = map_to_conf(conf);
2850 <  struct ClassItem *class = NULL;
2851 <
2852 <  if (class_name == NULL)
1348 >  if (class_name == NULL)
1349    {
1350 <    aconf->class_ptr = class_default;
1350 >    conf->class = class_default;
1351  
1352 <    if (conf->type == CLIENT_TYPE)
1353 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1354 <                           "Warning *** Defaulting to default class for %s@%s",
1355 <                           aconf->user, aconf->host);
1352 >    if (conf->type == CONF_CLIENT)
1353 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1354 >                           "Warning *** Defaulting to default class for %s@%s",
1355 >                           conf->user, conf->host);
1356      else
1357 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1358 <                           "Warning *** Defaulting to default class for %s",
1359 <                           conf->name);
1357 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1358 >                           "Warning *** Defaulting to default class for %s",
1359 >                           conf->name);
1360    }
1361    else
1362 <    aconf->class_ptr = find_class(class_name);
1362 >    conf->class = class_find(class_name, 1);
1363  
1364 <  if (aconf->class_ptr)
2869 <    class = map_to_conf(aconf->class_ptr);
2870 <
2871 <  if (aconf->class_ptr == NULL || !class->active)
1364 >  if (conf->class == NULL)
1365    {
1366 <    if (conf->type == CLIENT_TYPE)
1367 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1368 <                           "Warning *** Defaulting to default class for %s@%s",
1369 <                           aconf->user, aconf->host);
1366 >    if (conf->type == CONF_CLIENT)
1367 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1368 >                           "Warning *** Defaulting to default class for %s@%s",
1369 >                           conf->user, conf->host);
1370      else
1371 <      sendto_realops_flags(UMODE_ALL, L_ALL,
1372 <                           "Warning *** Defaulting to default class for %s",
1373 <                           conf->name);
1374 <    aconf->class_ptr = class_default;
2882 <  }
2883 < }
2884 <
2885 < /* conf_add_server()
2886 < *
2887 < * inputs       - pointer to config item
2888 < *              - pointer to link count already on this conf
2889 < * output       - NONE
2890 < * side effects - Add a connect block
2891 < */
2892 < int
2893 < conf_add_server(struct ConfItem *conf, const char *class_name)
2894 < {
2895 <  struct AccessItem *aconf = map_to_conf(conf);
2896 <
2897 <  conf_add_class_to_conf(conf, class_name);
2898 <
2899 <  if (!aconf->host || !conf->name)
2900 <  {
2901 <    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
2902 <    ilog(LOG_TYPE_IRCD, "Bad connect block");
2903 <    return -1;
2904 <  }
2905 <
2906 <  if (EmptyString(aconf->passwd))
2907 <  {
2908 <    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
2909 <                         conf->name);
2910 <    ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
2911 <    return -1;
1371 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1372 >                           "Warning *** Defaulting to default class for %s",
1373 >                           conf->name);
1374 >    conf->class = class_default;
1375    }
2913
2914  lookup_confhost(conf);
2915
2916  return 0;
1376   }
1377  
1378   /* yyerror()
# Line 2931 | Line 1390 | yyerror(const char *msg)
1390      return;
1391  
1392    strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1393 <  sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
1393 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1394 >                       "\"%s\", line %u: %s: %s",
1395 >                       conffilebuf, lineno + 1, msg, newlinebuf);
1396 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1397 >       conffilebuf, lineno + 1, msg, newlinebuf);
1398 > }
1399 >
1400 > void
1401 > conf_error_report(const char *msg)
1402 > {
1403 >  char newlinebuf[IRCD_BUFSIZE];
1404 >
1405 >  strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1406 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1407 >                       "\"%s\", line %u: %s: %s",
1408                         conffilebuf, lineno + 1, msg, newlinebuf);
1409    ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1410         conffilebuf, lineno + 1, msg, newlinebuf);
# Line 2939 | Line 1412 | yyerror(const char *msg)
1412  
1413   /*
1414   * valid_tkline()
1415 < *
1415 > *
1416   * inputs       - pointer to ascii string to check
1417   *              - whether the specified time is in seconds or minutes
1418   * output       - -1 not enough parameters
# Line 2948 | Line 1421 | yyerror(const char *msg)
1421   * Originally written by Dianora (Diane, db@db.net)
1422   */
1423   time_t
1424 < valid_tkline(const char *p, int minutes)
1424 > valid_tkline(const char *data, const int minutes)
1425   {
1426 +  const unsigned char *p = (const unsigned char *)data;
1427 +  unsigned char tmpch = '\0';
1428    time_t result = 0;
1429  
1430 <  for (; *p; ++p)
1430 >  while ((tmpch = *p++))
1431    {
1432 <    if (!IsDigit(*p))
1432 >    if (!IsDigit(tmpch))
1433        return 0;
1434  
1435      result *= 10;
1436 <    result += ((*p) & 0xF);
1436 >    result += (tmpch & 0xF);
1437    }
1438  
1439    /*
1440 <   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1440 >   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1441     * i.e. they specifically use 0, I am going to return 1 instead
1442     * as a return value of non-zero is used to flag it as a temporary kline
1443     */
1444    if (result == 0)
1445      result = 1;
1446  
1447 <  /*
1447 >  /*
1448     * If the incoming time is in seconds convert it to minutes for the purpose
1449     * of this calculation
1450     */
1451    if (!minutes)
1452 <    result = result / (time_t)60;
1452 >    result = result / 60;
1453  
1454    if (result > MAX_TDKLINE_TIME)
1455      result = MAX_TDKLINE_TIME;
1456  
1457 <  result = result * (time_t)60;  /* turn it into seconds */
1457 >  result = result * 60;  /* turn it into seconds */
1458  
1459    return result;
1460   }
1461  
1462 + /* valid_wild_card_simple()
1463 + *
1464 + * inputs       - data to check for sufficient non-wildcard characters
1465 + * outputs      - 1 if valid, else 0
1466 + * side effects - none
1467 + */
1468 + int
1469 + valid_wild_card_simple(const char *data)
1470 + {
1471 +  const unsigned char *p = (const unsigned char *)data;
1472 +  unsigned char tmpch = '\0';
1473 +  unsigned int nonwild = 0;
1474 +
1475 +  while ((tmpch = *p++))
1476 +  {
1477 +    if (tmpch == '\\' && *p)
1478 +    {
1479 +      ++p;
1480 +      if (++nonwild >= ConfigGeneral.min_nonwildcard_simple)
1481 +        return 1;
1482 +    }
1483 +    else if (!IsMWildChar(tmpch))
1484 +    {
1485 +      if (++nonwild >= ConfigGeneral.min_nonwildcard_simple)
1486 +        return 1;
1487 +    }
1488 +  }
1489 +
1490 +  return 0;
1491 + }
1492 +
1493   /* valid_wild_card()
1494   *
1495   * input        - pointer to client
# Line 2995 | Line 1501 | valid_tkline(const char *p, int minutes)
1501   int
1502   valid_wild_card(struct Client *source_p, int warn, int count, ...)
1503   {
1504 <  char *p;
1505 <  char tmpch;
3000 <  int nonwild = 0;
1504 >  unsigned char tmpch = '\0';
1505 >  unsigned int nonwild = 0;
1506    va_list args;
1507  
1508    /*
# Line 3016 | Line 1521 | valid_wild_card(struct Client *source_p,
1521  
1522    while (count--)
1523    {
1524 <    p = va_arg(args, char *);
1524 >    const unsigned char *p = va_arg(args, const unsigned char *);
1525      if (p == NULL)
1526        continue;
1527  
# Line 3028 | Line 1533 | valid_wild_card(struct Client *source_p,
1533           * If we find enough non-wild characters, we can
1534           * break - no point in searching further.
1535           */
1536 <        if (++nonwild >= ConfigFileEntry.min_nonwildcard)
1536 >        if (++nonwild >= ConfigGeneral.min_nonwildcard)
1537 >        {
1538 >          va_end(args);
1539            return 1;
1540 +        }
1541        }
1542      }
1543    }
1544  
1545    if (warn)
1546 <    sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
1547 <               me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
1546 >    sendto_one_notice(source_p, &me,
1547 >                      ":Please include at least %u non-wildcard characters with the mask",
1548 >                      ConfigGeneral.min_nonwildcard);
1549 >  va_end(args);
1550    return 0;
1551   }
1552  
# Line 3050 | Line 1560 | valid_wild_card(struct Client *source_p,
1560   *              - parse_flags bit map of things to test
1561   *              - pointer to user or string to parse into
1562   *              - pointer to host or NULL to parse into if non NULL
1563 < *              - pointer to optional tkline time or NULL
1563 > *              - pointer to optional tkline time or NULL
1564   *              - pointer to target_server to parse into if non NULL
1565   *              - pointer to reason to parse into
1566   *
# Line 3072 | Line 1582 | valid_wild_card(struct Client *source_p,
1582   */
1583   int
1584   parse_aline(const char *cmd, struct Client *source_p,
1585 <            int parc, char **parv,
1586 <            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1587 <            char **target_server, char **reason)
1585 >            int parc, char **parv,
1586 >            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1587 >            char **target_server, char **reason)
1588   {
1589    int found_tkline_time=0;
1590 <  static char def_reason[] = "No Reason";
1590 >  static char def_reason[] = CONF_NOREASON;
1591    static char user[USERLEN*4+1];
1592    static char host[HOSTLEN*4+1];
1593  
# Line 3095 | Line 1605 | parse_aline(const char *cmd, struct Clie
1605        *tkline_time = found_tkline_time;
1606      else
1607      {
1608 <      sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3099 <                 me.name, source_p->name, cmd);
1608 >      sendto_one_notice(source_p, &me, ":temp_line not supported by %s", cmd);
1609        return -1;
1610      }
1611    }
1612  
1613    if (parc == 0)
1614    {
1615 <    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3107 <               me.name, source_p->name, cmd);
1615 >    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1616      return -1;
1617    }
1618  
# Line 3118 | Line 1626 | parse_aline(const char *cmd, struct Clie
1626      *up_p = user;
1627      *h_p = host;
1628    }
1629 <
1629 >
1630    parc--;
1631    parv++;
1632  
# Line 3131 | Line 1639 | parse_aline(const char *cmd, struct Clie
1639  
1640        if (target_server == NULL)
1641        {
1642 <        sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
1643 <                   me.name, source_p->name, cmd);
3136 <        return -1;
1642 >        sendto_one_notice(source_p, &me, ":ON server not supported by %s", cmd);
1643 >        return -1;
1644        }
1645  
1646        if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
1647        {
1648 <        sendto_one(source_p, form_str(ERR_NOPRIVS),
3142 <                   me.name, source_p->name, "remoteban");
1648 >        sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "remoteban");
1649          return -1;
1650        }
1651  
1652        if (parc == 0 || EmptyString(*parv))
1653        {
1654 <        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
1655 <                   me.name, source_p->name, cmd);
3150 <        return -1;
1654 >        sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1655 >        return -1;
1656        }
1657  
1658        *target_server = *parv;
# Line 3160 | Line 1665 | parse_aline(const char *cmd, struct Clie
1665         * caller probably NULL'd it first, but no harm to do it again -db
1666         */
1667        if (target_server != NULL)
1668 <        *target_server = NULL;
1668 >        *target_server = NULL;
1669      }
1670    }
1671  
# Line 3168 | Line 1673 | parse_aline(const char *cmd, struct Clie
1673    {
1674      if (strchr(user, '!') != NULL)
1675      {
1676 <      sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3172 <                 me.name, source_p->name);
1676 >      sendto_one_notice(source_p, &me, ":Invalid character '!' in kline");
1677        return -1;
1678      }
1679  
# Line 3186 | Line 1690 | parse_aline(const char *cmd, struct Clie
1690      {
1691        *reason = *parv;
1692        if (!valid_comment(source_p, *reason, 1))
1693 <        return -1;
1693 >        return -1;
1694      }
1695      else
1696        *reason = def_reason;
# Line 3225 | Line 1729 | find_user_host(struct Client *source_p,
1729      {
1730        *(hostp++) = '\0';                       /* short and squat */
1731        if (*user_host_or_nick)
1732 <        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
1732 >        strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
1733        else
1734 <        strcpy(luser, "*");
1734 >        strcpy(luser, "*");
1735 >
1736        if (*hostp)
1737 <        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
1737 >        strlcpy(lhost, hostp, HOSTLEN + 1);    /* here is my host */
1738        else
1739 <        strcpy(lhost, "*");
1739 >        strcpy(lhost, "*");
1740      }
1741      else
1742      {
1743        luser[0] = '*';             /* no @ found, assume its *@somehost */
1744 <      luser[1] = '\0';    
1744 >      luser[1] = '\0';
1745        strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
1746      }
1747 <    
1747 >
1748      return 1;
1749    }
1750 <  else if (!(flags & NOUSERLOOKUP))
1750 >  else
1751    {
1752      /* Try to find user@host mask from nick */
1753      /* Okay to use source_p as the first param, because source_p == client_p */
1754 <    if ((target_p =
1755 <        find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
1756 <      return 0;
1754 >    if ((target_p =
1755 >        find_chasing(source_p, user_host_or_nick)) == NULL)
1756 >      return 0;  /* find_chasing sends ERR_NOSUCHNICK */
1757  
1758      if (IsExemptKline(target_p))
1759      {
1760 <      if (!IsServer(source_p))
1761 <        sendto_one(source_p,
3257 <                   ":%s NOTICE %s :%s is E-lined",
3258 <                   me.name, source_p->name, target_p->name);
1760 >      if (IsClient(source_p))
1761 >        sendto_one_notice(source_p, &me, ":%s is E-lined", target_p->name);
1762        return 0;
1763      }
1764  
# Line 3268 | Line 1771 | find_user_host(struct Client *source_p,
1771      if (target_p->username[0] == '~')
1772        luser[0] = '*';
1773  
1774 <    if (target_p->sockhost[0] == '\0' ||
3272 <        (target_p->sockhost[0] == '0' && target_p->sockhost[1] == '\0'))
1774 >    if (!strcmp(target_p->sockhost, "0"))
1775        strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
1776      else
1777        strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
# Line 3290 | Line 1792 | find_user_host(struct Client *source_p,
1792   int
1793   valid_comment(struct Client *source_p, char *comment, int warn)
1794   {
3293  if (strchr(comment, '"'))
3294  {
3295    if (warn)
3296      sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3297                 me.name, source_p->name);
3298    return 0;
3299  }
3300
1795    if (strlen(comment) > REASONLEN)
1796      comment[REASONLEN-1] = '\0';
1797  
# Line 3312 | Line 1806 | valid_comment(struct Client *source_p, c
1806   * side effects - none
1807   */
1808   int
1809 < match_conf_password(const char *password, const struct AccessItem *aconf)
1809 > match_conf_password(const char *password, const struct MaskItem *conf)
1810   {
1811    const char *encr = NULL;
1812  
1813 <  if (password == NULL || aconf->passwd == NULL)
1813 >  if (EmptyString(password) || EmptyString(conf->passwd))
1814      return 0;
1815  
1816 <  if (aconf->flags & CONF_FLAGS_ENCRYPTED)
1817 <  {
3324 <    /* use first two chars of the password they send in as salt */
3325 <    /* If the password in the conf is MD5, and ircd is linked
3326 <     * to scrypt on FreeBSD, or the standard crypt library on
3327 <     * glibc Linux, then this code will work fine on generating
3328 <     * the proper encrypted hash for comparison.
3329 <     */
3330 <    if (*aconf->passwd)
3331 <      encr = crypt(password, aconf->passwd);
3332 <    else
3333 <      encr = "";
3334 <  }
1816 >  if (conf->flags & CONF_FLAGS_ENCRYPTED)
1817 >    encr = crypt(password, conf->passwd);
1818    else
1819      encr = password;
1820  
1821 <  return !strcmp(encr, aconf->passwd);
1821 >  return encr && !strcmp(encr, conf->passwd);
1822   }
1823  
1824   /*
# Line 3343 | Line 1826 | match_conf_password(const char *password
1826   *
1827   * inputs       - client sending the cluster
1828   *              - command name "KLINE" "XLINE" etc.
1829 < *              - capab -- CAP_KLN etc. from s_serv.h
1829 > *              - capab -- CAP_KLN etc. from server.h
1830   *              - cluster type -- CLUSTER_KLINE etc. from conf.h
1831   *              - pattern and args to send along
1832   * output       - none
# Line 3355 | Line 1838 | cluster_a_line(struct Client *source_p,
1838                 int capab, int cluster_type, const char *pattern, ...)
1839   {
1840    va_list args;
1841 <  char buffer[IRCD_BUFSIZE];
1841 >  char buffer[IRCD_BUFSIZE] = "";
1842    const dlink_node *ptr = NULL;
1843  
1844    va_start(args, pattern);
# Line 3364 | Line 1847 | cluster_a_line(struct Client *source_p,
1847  
1848    DLINK_FOREACH(ptr, cluster_items.head)
1849    {
1850 <    const struct ConfItem *conf = ptr->data;
1850 >    const struct MaskItem *conf = ptr->data;
1851  
1852      if (conf->flags & cluster_type)
1853        sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
1854 <                         "%s %s %s", command, conf->name, buffer);
1854 >                         "%s %s %s", command, conf->name, buffer);
1855    }
1856   }
1857  
# Line 3416 | Line 1899 | split_nuh(struct split_nuh_item *const i
1899    {
1900      *p = '\0';
1901  
1902 <    if (iptr->nickptr && *iptr->nuhmask != '\0')
1902 >    if (iptr->nickptr && *iptr->nuhmask)
1903        strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
1904  
1905 <    if ((q = strchr(++p, '@'))) {
1905 >    if ((q = strchr(++p, '@')))
1906 >    {
1907        *q++ = '\0';
1908  
1909 <      if (*p != '\0')
1909 >      if (*p)
1910          strlcpy(iptr->userptr, p, iptr->usersize);
1911  
1912 <      if (*q != '\0')
1912 >      if (*q)
1913          strlcpy(iptr->hostptr, q, iptr->hostsize);
1914      }
1915      else
1916      {
1917 <      if (*p != '\0')
1917 >      if (*p)
1918          strlcpy(iptr->userptr, p, iptr->usersize);
1919      }
1920    }
# Line 3442 | Line 1926 | split_nuh(struct split_nuh_item *const i
1926        /* if found a @ */
1927        *p++ = '\0';
1928  
1929 <      if (*iptr->nuhmask != '\0')
1929 >      if (*iptr->nuhmask)
1930          strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
1931  
1932 <      if (*p != '\0')
1932 >      if (*p)
1933          strlcpy(iptr->hostptr, p, iptr->hostsize);
1934      }
1935      else
# Line 3458 | Line 1942 | split_nuh(struct split_nuh_item *const i
1942      }
1943    }
1944   }
3461
3462 /*
3463 * flags_to_ascii
3464 *
3465 * inputs       - flags is a bitmask
3466 *              - pointer to table of ascii letters corresponding
3467 *                to each bit
3468 *              - flag 1 for convert ToLower if bit missing
3469 *                0 if ignore.
3470 * output       - none
3471 * side effects - string pointed to by p has bitmap chars written to it
3472 */
3473 static void
3474 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3475               int lowerit)
3476 {
3477  unsigned int mask = 1;
3478  int i = 0;
3479
3480  for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3481  {
3482    if (flags & mask)
3483      *p++ = bit_table[i];
3484    else if (lowerit)
3485      *p++ = ToLower(bit_table[i]);
3486  }
3487  *p = '\0';
3488 }
3489
3490 /*
3491 * cidr_limit_reached
3492 *
3493 * inputs       - int flag allowing over_rule of limits
3494 *              - pointer to the ip to be added
3495 *              - pointer to the class
3496 * output       - non zero if limit reached
3497 *                0 if limit not reached
3498 * side effects -
3499 */
3500 static int
3501 cidr_limit_reached(int over_rule,
3502                   struct irc_ssaddr *ip, struct ClassItem *aclass)
3503 {
3504  dlink_node *ptr = NULL;
3505  struct CidrItem *cidr;
3506
3507  if (aclass->number_per_cidr <= 0)
3508    return 0;
3509
3510  if (ip->ss.ss_family == AF_INET)
3511  {
3512    if (aclass->cidr_bitlen_ipv4 <= 0)
3513      return 0;
3514
3515    DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3516    {
3517      cidr = ptr->data;
3518      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3519      {
3520        if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3521          return -1;
3522        cidr->number_on_this_cidr++;
3523        return 0;
3524      }
3525    }
3526    cidr = MyMalloc(sizeof(struct CidrItem));
3527    cidr->number_on_this_cidr = 1;
3528    cidr->mask = *ip;
3529    mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv4);
3530    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3531  }
3532 #ifdef IPV6
3533  else if (aclass->cidr_bitlen_ipv6 > 0)
3534  {
3535    DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3536    {
3537      cidr = ptr->data;
3538      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3539      {
3540        if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3541          return -1;
3542        cidr->number_on_this_cidr++;
3543        return 0;
3544      }
3545    }
3546    cidr = MyMalloc(sizeof(struct CidrItem));
3547    cidr->number_on_this_cidr = 1;
3548    cidr->mask = *ip;
3549    mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv6);
3550    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3551  }
3552 #endif
3553  return 0;
3554 }
3555
3556 /*
3557 * remove_from_cidr_check
3558 *
3559 * inputs       - pointer to the ip to be removed
3560 *              - pointer to the class
3561 * output       - NONE
3562 * side effects -
3563 */
3564 static void
3565 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3566 {
3567  dlink_node *ptr = NULL;
3568  dlink_node *next_ptr = NULL;
3569  struct CidrItem *cidr;
3570
3571  if (aclass->number_per_cidr == 0)
3572    return;
3573
3574  if (ip->ss.ss_family == AF_INET)
3575  {
3576    if (aclass->cidr_bitlen_ipv4 <= 0)
3577      return;
3578
3579    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3580    {
3581      cidr = ptr->data;
3582      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3583      {
3584        cidr->number_on_this_cidr--;
3585        if (cidr->number_on_this_cidr == 0)
3586        {
3587          dlinkDelete(ptr, &aclass->list_ipv4);
3588          MyFree(cidr);
3589          return;
3590        }
3591      }
3592    }
3593  }
3594 #ifdef IPV6
3595  else if (aclass->cidr_bitlen_ipv6 > 0)
3596  {
3597    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3598    {
3599      cidr = ptr->data;
3600      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3601      {
3602        cidr->number_on_this_cidr--;
3603        if (cidr->number_on_this_cidr == 0)
3604        {
3605          dlinkDelete(ptr, &aclass->list_ipv6);
3606          MyFree(cidr);
3607          return;
3608        }
3609      }
3610    }
3611  }
3612 #endif
3613 }
3614
3615 static void
3616 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3617                  dlink_list *old_list, dlink_list *new_list, int changed)
3618 {
3619  dlink_node *ptr;
3620  struct Client *client_p;
3621  struct ConfItem *conf;
3622  struct AccessItem *aconf;
3623
3624  if (!changed)
3625  {
3626    *new_list = *old_list;
3627    old_list->head = old_list->tail = NULL;
3628    old_list->length = 0;
3629    return;
3630  }
3631
3632  DLINK_FOREACH(ptr, local_client_list.head)
3633  {
3634    client_p = ptr->data;
3635    if (client_p->localClient->aftype != aftype)
3636      continue;
3637    if (dlink_list_length(&client_p->localClient->confs) == 0)
3638      continue;
3639
3640    conf = client_p->localClient->confs.tail->data;
3641    if (conf->type == CLIENT_TYPE)
3642    {
3643      aconf = map_to_conf(conf);
3644      if (aconf->class_ptr == oldcl)
3645        cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3646    }
3647  }
3648 }
3649
3650 /*
3651 * rebuild_cidr_class
3652 *
3653 * inputs       - pointer to old conf
3654 *              - pointer to new_class
3655 * output       - none
3656 * side effects - rebuilds the class link list of cidr blocks
3657 */
3658 void
3659 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3660 {
3661  struct ClassItem *old_class = map_to_conf(conf);
3662
3663  if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
3664  {
3665    if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
3666      rebuild_cidr_list(AF_INET, conf, new_class,
3667                        &old_class->list_ipv4, &new_class->list_ipv4,
3668                        old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
3669
3670 #ifdef IPV6
3671    if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
3672      rebuild_cidr_list(AF_INET6, conf, new_class,
3673                        &old_class->list_ipv6, &new_class->list_ipv6,
3674                        old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
3675 #endif
3676  }
3677
3678  destroy_cidr_class(old_class);
3679 }
3680
3681 /*
3682 * destroy_cidr_list
3683 *
3684 * inputs       - pointer to class dlink list of cidr blocks
3685 * output       - none
3686 * side effects - completely destroys the class link list of cidr blocks
3687 */
3688 static void
3689 destroy_cidr_list(dlink_list *list)
3690 {
3691  dlink_node *ptr = NULL, *next_ptr = NULL;
3692
3693  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3694  {
3695    dlinkDelete(ptr, list);
3696    MyFree(ptr->data);
3697  }
3698 }
3699
3700 /*
3701 * destroy_cidr_class
3702 *
3703 * inputs       - pointer to class
3704 * output       - none
3705 * side effects - completely destroys the class link list of cidr blocks
3706 */
3707 static void
3708 destroy_cidr_class(struct ClassItem *aclass)
3709 {
3710  destroy_cidr_list(&aclass->list_ipv4);
3711  destroy_cidr_list(&aclass->list_ipv6);
3712 }

Diff Legend

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