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-7.2/src/s_conf.c (file contents), Revision 855 by db, Mon Feb 26 22:06:45 2007 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 < *  s_conf.c: Configuration file functions.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 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"
30 < #include "tools.h"
31 < #include "s_conf.h"
32 < #include "s_serv.h"
30 > #include "conf.h"
31 > #include "conf_pseudo.h"
32 > #include "server.h"
33   #include "resv.h"
31 #include "s_stats.h"
34   #include "channel.h"
35   #include "client.h"
34 #include "common.h"
36   #include "event.h"
36 #include "hash.h"
37 #include "hook.h"
37   #include "irc_string.h"
39 #include "sprintf_irc.h"
38   #include "s_bsd.h"
41 #include "irc_getnameinfo.h"
42 #include "irc_getaddrinfo.h"
39   #include "ircd.h"
44 #include "list.h"
40   #include "listener.h"
41   #include "hostmask.h"
42   #include "modules.h"
43   #include "numeric.h"
44   #include "fdlist.h"
45 < #include "s_log.h"
45 > #include "log.h"
46   #include "send.h"
52 #include "s_gline.h"
53 #include "fileio.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 "misc.h"
54 + #include "conf_db.h"
55 + #include "conf_class.h"
56 + #include "motd.h"
57 + #include "ipcache.h"
58  
60 struct Callback *client_check_cb = NULL;
61 struct config_server_hide ConfigServerHide;
59  
60   /* general conf items link list root, other than k lines etc. */
61 + dlink_list service_items = { NULL, NULL, 0 };
62   dlink_list server_items  = { NULL, NULL, 0 };
63   dlink_list cluster_items = { NULL, NULL, 0 };
66 dlink_list hub_items     = { NULL, NULL, 0 };
67 dlink_list leaf_items    = { NULL, NULL, 0 };
64   dlink_list oconf_items   = { NULL, NULL, 0 };
65   dlink_list uconf_items   = { NULL, NULL, 0 };
66   dlink_list xconf_items   = { NULL, NULL, 0 };
71 dlink_list rxconf_items  = { NULL, NULL, 0 };
72 dlink_list rkconf_items  = { NULL, NULL, 0 };
67   dlink_list nresv_items   = { NULL, NULL, 0 };
68 < dlink_list class_items   = { NULL, NULL, 0 };
75 < dlink_list gdeny_items   = { NULL, NULL, 0 };
76 <
77 < dlink_list temporary_klines  = { NULL, NULL, 0 };
78 < dlink_list temporary_dlines  = { NULL, NULL, 0 };
79 < dlink_list temporary_xlines  = { NULL, NULL, 0 };
80 < dlink_list temporary_rklines = { NULL, NULL, 0 };
81 < dlink_list temporary_glines  = { NULL, NULL, 0 };
82 < dlink_list temporary_rxlines = { NULL, NULL, 0 };
83 < 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];
88 extern char yytext[];
73   extern int yyparse(); /* defined in y.tab.c */
90 int ypass = 1; /* used by yyparse()      */
74  
75   /* internally defined functions */
76 < static void lookup_confhost(struct ConfItem *);
94 < static void set_default_conf(void);
95 < static void validate_conf(void);
96 < static void read_conf(FBFILE *);
76 > static void read_conf(FILE *);
77   static void clear_out_old_conf(void);
98 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 *);
103 < static int attach_iline(struct Client *, struct ConfItem *);
104 < static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
105 < static void parse_conf_file(int, int);
106 < static dlink_list *map_to_list(ConfType);
107 < 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  
110 /*
111 * bit_len
112 */
113 static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
114 static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
115 static void destroy_cidr_class(struct ClassItem *);
116
117 static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
118
119 FBFILE *conf_fbfile_in = NULL;
120
121 /* address of default class conf */
122 static struct ConfItem *class_default;
123
124 /* usually, with hash tables, you use a prime number...
125 * but in this case I am dealing with ip addresses,
126 * not ascii strings.
127 */
128 #define IP_HASH_SIZE 0x1000
129
130 struct ip_entry
131 {
132  struct irc_ssaddr ip;
133  int count;
134  time_t last_attempt;
135  struct ip_entry *next;
136 };
137
138 static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
139 static BlockHeap *ip_entry_heap = NULL;
140 static int ip_entries_count = 0;
141
142
143 inline void *
144 map_to_conf(struct ConfItem *aconf)
145 {
146  void *conf;
147  conf = (void *)((unsigned long)aconf +
148                  (unsigned long)sizeof(struct ConfItem));
149  return(conf);
150 }
151
152 inline struct ConfItem *
153 unmap_conf_item(void *aconf)
154 {
155  struct ConfItem *conf;
156
157  conf = (struct ConfItem *)((unsigned long)aconf -
158                             (unsigned long)sizeof(struct ConfItem));
159  return(conf);
160 }
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 170 | 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, struct DNSReply *reply)
96 > conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name, size_t namelength)
97   {
98 <  struct AccessItem *aconf = (struct AccessItem *)vptr;
176 <  struct ConfItem *conf;
98 >  struct MaskItem *conf = vptr;
99  
100 <  MyFree(aconf->dns_query);
179 <  aconf->dns_query = NULL;
100 >  conf->dns_pending = 0;
101  
102 <  if (reply != NULL)
103 <    memcpy(&aconf->ipnum, &reply->addr, sizeof(reply->addr));
104 <  else {
105 <    ilog(L_NOTICE, "Host not found: %s, ignoring connect{} block",
185 <         aconf->host);
186 <    conf = unmap_conf_item(aconf);
187 <    sendto_realops_flags(UMODE_ALL, L_ALL,
188 <                         "Ignoring connect{} block for %s - host not found",
189 <                         conf->name);
190 <    delete_conf_item(conf);
191 <  }
102 >  if (addr)
103 >    memcpy(&conf->addr, addr, sizeof(conf->addr));
104 >  else
105 >    conf->dns_failed = 1;
106   }
107  
108   /* conf_dns_lookup()
# Line 198 | Line 112 | conf_dns_callback(void *vptr, struct DNS
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_query == NULL)
117 >  if (!conf->dns_pending)
118    {
119 <    aconf->dns_query = MyMalloc(sizeof(struct DNSQuery));
120 <    aconf->dns_query->ptr = aconf;
121 <    aconf->dns_query->callback = conf_dns_callback;
122 <    gethost_byname(aconf->host, aconf->dns_query);
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 < *
214 < * inputs       - type of item
215 < * output       - pointer to new conf entry
216 < * side effects - none
217 < */
218 < struct ConfItem *
219 < 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;
223 <  struct ClassItem *aclass = NULL;
224 <  int status = 0;
225 <
226 <  switch (type)
227 <  {
228 <  case DLINE_TYPE:
229 <  case EXEMPTDLINE_TYPE:
230 <  case GLINE_TYPE:
231 <  case KLINE_TYPE:
232 <  case CLIENT_TYPE:
233 <  case OPER_TYPE:
234 <  case SERVER_TYPE:
235 <    conf = MyMalloc(sizeof(struct ConfItem) +
236 <                    sizeof(struct AccessItem));
237 <    aconf = map_to_conf(conf);
238 <    aconf->aftype = AF_INET;
239 <
240 <    /* Yes, sigh. switch on type again */
241 <    switch (type)
242 <    {
243 <    case EXEMPTDLINE_TYPE:
244 <      status = CONF_EXEMPTDLINE;
245 <      break;
246 <
247 <    case DLINE_TYPE:
248 <      status = CONF_DLINE;
249 <      break;
250 <
251 <    case KLINE_TYPE:
252 <      status = CONF_KLINE;
253 <      break;
254 <
255 <    case GLINE_TYPE:
256 <      status = CONF_GLINE;
257 <      break;
258 <
259 <    case CLIENT_TYPE:
260 <      status = CONF_CLIENT;
261 <      break;
131 >  struct MaskItem *conf = MyCalloc(sizeof(*conf));
132 >  dlink_list *list = NULL;
133  
134 <    case OPER_TYPE:
135 <      status = CONF_OPERATOR;
136 <      dlinkAdd(conf, &conf->node, &oconf_items);
266 <      break;
267 <
268 <    case SERVER_TYPE:
269 <      status = CONF_SERVER;
270 <      dlinkAdd(conf, &conf->node, &server_items);
271 <      break;
272 <
273 <    default:
274 <      break;
275 <    }
276 <    aconf->status = status;
277 <    break;
278 <
279 <  case LEAF_TYPE:
280 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
281 <                                       sizeof(struct MatchItem));
282 <    dlinkAdd(conf, &conf->node, &leaf_items);
283 <    break;
284 <
285 <  case HUB_TYPE:
286 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
287 <                                       sizeof(struct MatchItem));
288 <    dlinkAdd(conf, &conf->node, &hub_items);
289 <    break;
290 <
291 <  case ULINE_TYPE:
292 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
293 <                                       sizeof(struct MatchItem));
294 <    dlinkAdd(conf, &conf->node, &uconf_items);
295 <    break;
296 <
297 <  case GDENY_TYPE:
298 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
299 <                                       sizeof(struct AccessItem));
300 <    dlinkAdd(conf, &conf->node, &gdeny_items);
301 <    break;
302 <
303 <  case XLINE_TYPE:
304 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
305 <                                       sizeof(struct MatchItem));
306 <    dlinkAdd(conf, &conf->node, &xconf_items);
307 <    break;
308 <
309 <  case RXLINE_TYPE:
310 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
311 <                                       sizeof(struct MatchItem));
312 <    dlinkAdd(conf, &conf->node, &rxconf_items);
313 <    break;
314 <
315 <  case RKLINE_TYPE:
316 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
317 <                                       sizeof(struct AccessItem));
318 <    aconf = map_to_conf(conf);
319 <    aconf->status = CONF_KLINE;
320 <    dlinkAdd(conf, &conf->node, &rkconf_items);
321 <    break;
322 <
323 <  case CLUSTER_TYPE:
324 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
325 <    dlinkAdd(conf, &conf->node, &cluster_items);
326 <    break;
327 <
328 <  case CRESV_TYPE:
329 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
330 <                                       sizeof(struct ResvChannel));
331 <    break;
332 <
333 <  case NRESV_TYPE:
334 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
335 <                                       sizeof(struct MatchItem));
336 <    dlinkAdd(conf, &conf->node, &nresv_items);
337 <    break;
338 <
339 <  case CLASS_TYPE:
340 <    conf = MyMalloc(sizeof(struct ConfItem) +
341 <                           sizeof(struct ClassItem));
342 <    dlinkAdd(conf, &conf->node, &class_items);
343 <
344 <    aclass = map_to_conf(conf);
345 <    aclass->active = 1;
346 <    ConFreq(aclass) = DEFAULT_CONNECTFREQUENCY;
347 <    PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
348 <    MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
349 <    MaxSendq(aclass) = DEFAULT_SENDQ;
350 <
351 <    break;
352 <
353 <  default:
354 <    conf = NULL;
355 <    break;
356 <  }
357 <
358 <  /* XXX Yes, this will core if default is hit. I want it to for now - db */
359 <  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;
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);
373  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_query != NULL)
166 <    {
167 <      delete_resolver_queries(aconf->dns_query);
168 <      MyFree(aconf->dns_query);
390 <    }
391 <    if (aconf->passwd != NULL)
392 <      memset(aconf->passwd, 0, strlen(aconf->passwd));
393 <    if (aconf->spasswd != NULL)
394 <      memset(aconf->spasswd, 0, strlen(aconf->spasswd));
395 <    aconf->class_ptr = NULL;
396 <
397 <    MyFree(aconf->passwd);
398 <    MyFree(aconf->spasswd);
399 <    MyFree(aconf->reason);
400 <    MyFree(aconf->oper_reason);
401 <    MyFree(aconf->user);
402 <    MyFree(aconf->host);
403 <    MyFree(aconf->fakename);
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)
406 <      RSA_free(aconf->rsa_public_key);
407 <    MyFree(aconf->rsa_public_key_file);
408 < #endif
170 >  MyFree(conf->cipher_list);
171  
172 <    /* Yes, sigh. switch on type again */
173 <    switch(type)
174 <    {
175 <    case EXEMPTDLINE_TYPE:
176 <    case DLINE_TYPE:
177 <    case GLINE_TYPE:
178 <    case KLINE_TYPE:
179 <    case CLIENT_TYPE:
418 <      MyFree(conf);
419 <      break;
420 <
421 <    case OPER_TYPE:
422 <      aconf = map_to_conf(conf);
423 <      if (!IsConfIllegal(aconf))
424 <        dlinkDelete(&conf->node, &oconf_items);
425 <      MyFree(conf);
426 <      break;
427 <
428 <    case SERVER_TYPE:
429 <      aconf = map_to_conf(conf);
430 <      if (!IsConfIllegal(aconf))
431 <        dlinkDelete(&conf->node, &server_items);
432 <      MyFree(conf);
433 <      break;
434 <
435 <    default:
436 <      break;
437 <    }
438 <    break;
439 <
440 <  case HUB_TYPE:
441 <    match_item = map_to_conf(conf);
442 <    MyFree(match_item->user);
443 <    MyFree(match_item->host);
444 <    MyFree(match_item->reason);
445 <    MyFree(match_item->oper_reason);
446 <    /* If marked illegal, its already been pulled off of the hub_items list */
447 <    if (!match_item->illegal)
448 <      dlinkDelete(&conf->node, &hub_items);
449 <    MyFree(conf);
450 <    break;
451 <
452 <  case LEAF_TYPE:
453 <    match_item = map_to_conf(conf);
454 <    MyFree(match_item->user);
455 <    MyFree(match_item->host);
456 <    MyFree(match_item->reason);
457 <    MyFree(match_item->oper_reason);
458 <    /* If marked illegal, its already been pulled off of the leaf_items list */
459 <    if (!match_item->illegal)
460 <      dlinkDelete(&conf->node, &leaf_items);
461 <    MyFree(conf);
462 <    break;
463 <
464 <  case ULINE_TYPE:
465 <    match_item = map_to_conf(conf);
466 <    MyFree(match_item->user);
467 <    MyFree(match_item->host);
468 <    MyFree(match_item->reason);
469 <    MyFree(match_item->oper_reason);
470 <    dlinkDelete(&conf->node, &uconf_items);
471 <    MyFree(conf);
472 <    break;
473 <
474 <  case XLINE_TYPE:
475 <    match_item = map_to_conf(conf);
476 <    MyFree(match_item->user);
477 <    MyFree(match_item->host);
478 <    MyFree(match_item->reason);
479 <    MyFree(match_item->oper_reason);
480 <    dlinkDelete(&conf->node, &xconf_items);
481 <    MyFree(conf);
482 <    break;
483 <
484 <  case RKLINE_TYPE:
485 <    aconf = map_to_conf(conf);
486 <    MyFree(aconf->regexuser);
487 <    MyFree(aconf->regexhost);
488 <    MyFree(aconf->user);
489 <    MyFree(aconf->host);
490 <    MyFree(aconf->reason);
491 <    MyFree(aconf->oper_reason);
492 <    dlinkDelete(&conf->node, &rkconf_items);
493 <    MyFree(conf);
494 <    break;
495 <
496 <  case RXLINE_TYPE:
497 <    MyFree(conf->regexpname);
498 <    match_item = map_to_conf(conf);
499 <    MyFree(match_item->user);
500 <    MyFree(match_item->host);
501 <    MyFree(match_item->reason);
502 <    MyFree(match_item->oper_reason);
503 <    dlinkDelete(&conf->node, &rxconf_items);
504 <    MyFree(conf);
505 <    break;
506 <
507 <  case NRESV_TYPE:
508 <    match_item = map_to_conf(conf);
509 <    MyFree(match_item->user);
510 <    MyFree(match_item->host);
511 <    MyFree(match_item->reason);
512 <    MyFree(match_item->oper_reason);
513 <    dlinkDelete(&conf->node, &nresv_items);
514 <
515 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
516 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
517 <        free_dlink_node(m);
518 <
519 <    MyFree(conf);
520 <    break;
521 <
522 <  case GDENY_TYPE:
523 <    aconf = map_to_conf(conf);
524 <    MyFree(aconf->user);
525 <    MyFree(aconf->host);
526 <    dlinkDelete(&conf->node, &gdeny_items);
527 <    MyFree(conf);
528 <    break;
529 <
530 <  case CLUSTER_TYPE:
531 <    dlinkDelete(&conf->node, &cluster_items);
532 <    MyFree(conf);
533 <    break;
534 <
535 <  case CRESV_TYPE:
536 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
537 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
538 <        free_dlink_node(m);
539 <
540 <    MyFree(conf);
541 <    break;
542 <
543 <  case CLASS_TYPE:
544 <    dlinkDelete(&conf->node, &class_items);
545 <    MyFree(conf);
546 <    break;
547 <
548 <  default:
549 <    break;
172 >  if (conf->rsa_public_key)
173 >    RSA_free(conf->rsa_public_key);
174 > #endif
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    }
551 }
552
553 /* free_access_item()
554 *
555 * inputs       - pointer to conf to free
556 * output       - none
557 * side effects - crucial password fields are zeroed, conf is freed
558 */
559 void
560 free_access_item(struct AccessItem *aconf)
561 {
562  struct ConfItem *conf;
563
564  if (aconf == NULL)
565    return;
566  conf = unmap_conf_item(aconf);
567  delete_conf_item(conf);
568 }
181  
182 < static const unsigned int shared_bit_table[] =
571 <  { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
572 <
573 < /* report_confitem_types()
574 < *
575 < * inputs       - pointer to client requesting confitem report
576 < *              - ConfType to report
577 < * output       - none
578 < * side effects -
579 < */
580 < void
581 < report_confitem_types(struct Client *source_p, ConfType type, int temp)
582 < {
583 <  dlink_node *ptr = NULL;
584 <  struct ConfItem *conf = NULL;
585 <  struct AccessItem *aconf = NULL;
586 <  struct MatchItem *matchitem = NULL;
587 <  struct ClassItem *classitem = NULL;
588 <  char buf[12];
589 <  char *p = NULL;
590 <  const char *pfx = NULL;
591 <
592 <  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;
598 <      aconf = map_to_conf(conf);
599 <
600 <      p = buf;
601 <
602 <      if (aconf->flags & GDENY_BLOCK)
603 <        *p++ = 'B';
604 <      else
605 <        *p++ = 'b';
606 <
607 <      if (aconf->flags & GDENY_REJECT)
608 <        *p++ = 'R';
609 <      else
610 <        *p++ = 'r';
611 <
612 <      *p = '\0';
613 <
614 <      sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
615 <                 me.name, RPL_STATSDEBUG, source_p->name,
616 <                 aconf->user, aconf->host, conf->name, buf);
617 <    }
618 <    break;
619 <
620 <  case XLINE_TYPE:
621 <    DLINK_FOREACH(ptr, xconf_items.head)
622 <    {
623 <      conf = ptr->data;
624 <      matchitem = map_to_conf(conf);
625 <
626 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
627 <                 me.name, source_p->name,
628 <                 matchitem->hold ? "x": "X", matchitem->count,
629 <                 conf->name, matchitem->reason);
630 <    }
631 <    break;
632 <
633 <  case RXLINE_TYPE:
634 <    DLINK_FOREACH(ptr, rxconf_items.head)
635 <    {
636 <      conf = ptr->data;
637 <      matchitem = map_to_conf(conf);
638 <
639 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
640 <                 me.name, source_p->name,
641 <                 matchitem->hold ? "xR": "XR", matchitem->count,
642 <                 conf->name, matchitem->reason);
643 <    }
644 <    break;
645 <
646 <  case RKLINE_TYPE:
647 <    pfx = temp ? "kR" : "KR";
648 <
649 <    DLINK_FOREACH(ptr, rkconf_items.head)
650 <    {
651 <      aconf = map_to_conf((conf = ptr->data));
652 <
653 <      if (temp && !(conf->flags & CONF_FLAGS_TEMPORARY))
654 <        continue;
655 <
656 <      sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
657 <                 source_p->name, pfx, aconf->host, aconf->user,
658 <                 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
659 <    }
660 <    break;
661 <
662 <  case ULINE_TYPE:
663 <    DLINK_FOREACH(ptr, uconf_items.head)
664 <    {
665 <      conf = ptr->data;
666 <      matchitem = map_to_conf(conf);
667 <
668 <      p = buf;
669 <
670 <      /* some of these are redundant for the sake of
671 <       * consistency with cluster{} flags
672 <       */
673 <      *p++ = 'c';
674 <      flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
675 <
676 <      sendto_one(source_p, form_str(RPL_STATSULINE),
677 <                 me.name, source_p->name, conf->name,
678 <                 matchitem->user?matchitem->user: "*",
679 <                 matchitem->host?matchitem->host: "*", buf);
680 <    }
681 <
682 <    DLINK_FOREACH(ptr, cluster_items.head)
683 <    {
684 <      conf = ptr->data;
685 <
686 <      p = buf;
687 <
688 <      *p++ = 'C';
689 <      flags_to_ascii(conf->flags, shared_bit_table, p, 0);
690 <
691 <      sendto_one(source_p, form_str(RPL_STATSULINE),
692 <                 me.name, source_p->name, conf->name,
693 <                 "*", "*", buf);
694 <    }
695 <
696 <    break;
697 <
698 <  case OPER_TYPE:
699 <    DLINK_FOREACH(ptr, oconf_items.head)
700 <    {
701 <      conf = ptr->data;
702 <      aconf = map_to_conf(conf);
703 <
704 <      /* Don't allow non opers to see oper privs */
705 <      if (IsOper(source_p))
706 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
707 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
708 <                   conf->name, oper_privs_as_string(aconf->port),
709 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
710 <      else
711 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
712 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
713 <                   conf->name, "0",
714 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
715 <    }
716 <    break;
717 <
718 <  case CLASS_TYPE:
719 <    DLINK_FOREACH(ptr, class_items.head)
720 <    {
721 <      conf = ptr->data;
722 <      classitem = map_to_conf(conf);
723 <      sendto_one(source_p, form_str(RPL_STATSYLINE),
724 <                 me.name, source_p->name, 'Y',
725 <                 conf->name, PingFreq(classitem),
726 <                 ConFreq(classitem),
727 <                 MaxTotal(classitem), MaxSendq(classitem),
728 <                 CurrUserCount(classitem),
729 <                 classitem->active ? "active" : "disabled");
730 <    }
731 <    break;
732 <
733 <  case CONF_TYPE:
734 <  case CLIENT_TYPE:
735 <    break;
736 <
737 <  case SERVER_TYPE:
738 <    DLINK_FOREACH(ptr, server_items.head)
739 <    {
740 <      p = buf;
741 <
742 <      conf = ptr->data;
743 <      aconf = map_to_conf(conf);
744 <
745 <      buf[0] = '\0';
746 <
747 <      if (IsConfAllowAutoConn(aconf))
748 <        *p++ = 'A';
749 <      if (IsConfCryptLink(aconf))
750 <        *p++ = 'C';
751 <      if (IsConfLazyLink(aconf))
752 <        *p++ = 'L';
753 <      if (aconf->fakename)
754 <        *p++ = 'M';
755 <      if (IsConfTopicBurst(aconf))
756 <        *p++ = 'T';
757 <      if (IsConfCompressed(aconf))
758 <        *p++ = 'Z';
759 <      if (buf[0] == '\0')
760 <        *p++ = '*';
761 <
762 <      *p = '\0';
763 <
764 <      /*
765 <       * Allow admins to see actual ips unless hide_server_ips is enabled
766 <       */
767 <      if (!ConfigServerHide.hide_server_ips && IsAdmin(source_p))
768 <        sendto_one(source_p, form_str(RPL_STATSCLINE),
769 <                   me.name, source_p->name, 'C', aconf->host,
770 <                   buf, conf->name, aconf->port,
771 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
772 <        else
773 <          sendto_one(source_p, form_str(RPL_STATSCLINE),
774 <                     me.name, source_p->name, 'C',
775 <                     "*@127.0.0.1", buf, conf->name, aconf->port,
776 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
777 <    }
778 <    break;
779 <
780 <  case HUB_TYPE:
781 <    DLINK_FOREACH(ptr, hub_items.head)
782 <    {
783 <      conf = ptr->data;
784 <      matchitem = map_to_conf(conf);
785 <      sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
786 <                 source_p->name, 'H', matchitem->host, conf->name, 0, "*");
787 <    }
788 <    break;
184 >    MyFree(ptr->data);
185 >    dlinkDelete(ptr, &conf->leaf_list);
186 >    free_dlink_node(ptr);
187 >  }
188  
189 <  case LEAF_TYPE:
190 <    DLINK_FOREACH(ptr, leaf_items.head)
191 <    {
793 <      conf = ptr->data;
794 <      matchitem = map_to_conf(conf);
795 <      sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
796 <                 source_p->name, 'L', matchitem->host, conf->name, 0, "*");
797 <    }
798 <    break;
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:
805 <  case NRESV_TYPE:
806 <  case CLUSTER_TYPE:
807 <    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 821 | 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   {
827  struct Client *source_p = va_arg(args, struct Client *);
828  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)))
833 <    ilog(L_INFO, "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);
232 <      ilog(L_INFO,"Too many connections on IP from %s.",
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");
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));
234 >      ++ServerStats.is_ref;
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);
243 <      ilog(L_INFO,"Too many connections from %s.",
244 <           get_client_name(source_p, SHOW_IP));
245 <       ServerStats->is_ref++;
246 <      exit_client(source_p, &me,
858 <                "No more connections allowed in your connection class");
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));
245 >      ++ServerStats.is_ref;
246 >      exit_client(source_p, "No more connections allowed in your connection class");
247        break;
248  
249      case NOT_AUTHORIZED:
250 <    {
863 <      static char ipaddr[HOSTIPLEN];
864 <      ServerStats->is_ref++;
250 >      ++ServerStats.is_ref;
251        /* jdc - lists server name & port connections are on */
252        /*       a purely cosmetical change */
253 <      irc_getnameinfo((struct sockaddr*)&source_p->localClient->ip,
254 <            source_p->localClient->ip.ss_len, ipaddr, HOSTIPLEN, NULL, 0,
255 <            NI_NUMERICHOST);
256 <      sendto_realops_flags(UMODE_UNAUTH, L_ALL,
257 <                           "Unauthorized client connection from %s [%s] on [%s/%u].",
258 <                           get_client_name(source_p, SHOW_IP),
259 <                           ipaddr,
260 <                           source_p->localClient->listener->name,
261 <                           source_p->localClient->listener->port);
262 <      ilog(L_INFO,
263 <          "Unauthorized client connection from %s on [%s/%u].",
264 <          get_client_name(source_p, SHOW_IP),
265 <          source_p->localClient->listener->name,
880 <          source_p->localClient->listener->port);
881 <
882 <      /* XXX It is prolematical whether it is better to use the
883 <       * capture reject code here or rely on the connecting too fast code.
884 <       * - Dianora
885 <       */
886 <      if (REJECT_HOLD_TIME > 0)
887 <      {
888 <        sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
889 <                   me.name, source_p->name);
890 <        source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
891 <        SetCaptured(source_p);
892 <      }
893 <      else
894 <        exit_client(source_p, &me, "You are not authorized to use this server");
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->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 <    }
897 <
267 >
268     case BANNED_CLIENT:
269 <     /*
270 <      * Don't exit them immediately, play with them a bit.
901 <      * - Dianora
902 <      */
903 <     if (REJECT_HOLD_TIME > 0)
904 <     {
905 <       source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
906 <       SetCaptured(source_p);
907 <     }
908 <     else
909 <       exit_client(source_p, &me, "Banned");
910 <     ServerStats->is_ref++;
269 >     exit_client(source_p, "Banned");
270 >     ++ServerStats.is_ref;
271       break;
272  
273     case 0:
# Line 915 | 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
924 *              - 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;
933 <  char non_ident[USERLEN + 1] = { '~', '\0' };
934 <  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;
953 <  uhi[1] = client_p->host;
954 <  uhi[2] = client_p->sockhost;
955 <
956 <  rkconf = find_regexp_kline(uhi);
957 <
958 <  if (aconf != NULL)
309 >  if (conf)
310    {
311 <    if (IsConfClient(aconf) && !rkconf)
311 >    if (IsConfClient(conf))
312      {
313 <      conf = unmap_conf_item(aconf);
963 <
964 <      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);
970 <        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))
982 <          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,
996 <                   client_p->name);
997 <      if (ConfigFileEntry.kline_with_reason)
998 <        sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
999 <                  me.name, client_p->name, aconf->reason);
1000 <      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 1012 | 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;
1018 <  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);
1026 <
1027 <  aconf = map_to_conf(conf);
1028 <  if (aconf->class_ptr == NULL)
1029 <    return NOT_AUTHORIZED;  /* If class is missing, this is best */
1030 <
1031 <  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 1037 | Line 372 | attach_iline(struct Client *client_p, st
372     * setting a_limit_reached if any limit is reached.
373     * - Dianora
374     */
375 <  if (MaxTotal(aclass) != 0 && CurrUserCount(aclass) >= MaxTotal(aclass))
375 >  if (class->max_total && class->ref_count >= class->max_total)
376      a_limit_reached = 1;
377 <  else if (MaxPerIp(aclass) != 0 && ip_found->count > MaxPerIp(aclass))
377 >  else if (class->max_perip && ip_found->count > class->max_perip)
378      a_limit_reached = 1;
379 <  else if (MaxLocal(aclass) != 0 && local >= MaxLocal(aclass))
379 >  else if (class->max_local && local >= class->max_local)
380      a_limit_reached = 1;
381 <  else if (MaxGlobal(aclass) != 0 && global >= MaxGlobal(aclass))
381 >  else if (class->max_global && global >= class->max_global)
382      a_limit_reached = 1;
383 <  else if (MaxIdent(aclass) != 0 && ident >= MaxIdent(aclass) &&
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, "
1059 <               "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  
1065 /* init_ip_hash_table()
1066 *
1067 * inputs               - NONE
1068 * output               - NONE
1069 * side effects         - allocate memory for ip_entry(s)
1070 *                      - clear the ip hash table
1071 */
1072 void
1073 init_ip_hash_table(void)
1074 {
1075  ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
1076    2 * hard_fdlimit);
1077  memset(ip_hash_table, 0, sizeof(ip_hash_table));
1078 }
1079
1080 /* find_or_add_ip()
1081 *
1082 * inputs       - pointer to struct irc_ssaddr
1083 * output       - pointer to a struct ip_entry
1084 * side effects -
1085 *
1086 * If the ip # was not found, a new struct ip_entry is created, and the ip
1087 * count set to 0.
1088 */
1089 static struct ip_entry *
1090 find_or_add_ip(struct irc_ssaddr *ip_in)
1091 {
1092  struct ip_entry *ptr, *newptr;
1093  int hash_index = hash_ip(ip_in), res;
1094  struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1095 #ifdef IPV6
1096  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1097 #endif
1098
1099  for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1100  {
1101 #ifdef IPV6
1102    if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1103      continue;
1104    if (ip_in->ss.ss_family == AF_INET6)
1105    {
1106      ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1107      res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1108    }
1109    else
1110 #endif
1111    {
1112      ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1113      res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1114    }
1115    if (res == 0)
1116    {
1117      /* Found entry already in hash, return it. */
1118      return ptr;
1119    }
1120  }
1121
1122  if (ip_entries_count >= 2 * hard_fdlimit)
1123    garbage_collect_ip_entries();
1124
1125  newptr = BlockHeapAlloc(ip_entry_heap);
1126  ip_entries_count++;
1127  memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
1128
1129  newptr->next = ip_hash_table[hash_index];
1130  ip_hash_table[hash_index] = newptr;
1131
1132  return newptr;
1133 }
1134
1135 /* remove_one_ip()
1136 *
1137 * inputs        - unsigned long IP address value
1138 * output        - NONE
1139 * side effects  - The ip address given, is looked up in ip hash table
1140 *                 and number of ip#'s for that ip decremented.
1141 *                 If ip # count reaches 0 and has expired,
1142 *                 the struct ip_entry is returned to the ip_entry_heap
1143 */
1144 void
1145 remove_one_ip(struct irc_ssaddr *ip_in)
1146 {
1147  struct ip_entry *ptr;
1148  struct ip_entry *last_ptr = NULL;
1149  int hash_index = hash_ip(ip_in), res;
1150  struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1151 #ifdef IPV6
1152  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1153 #endif
1154
1155  for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1156  {
1157 #ifdef IPV6
1158    if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1159      continue;
1160    if (ip_in->ss.ss_family == AF_INET6)
1161    {
1162      ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1163      res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1164    }
1165    else
1166 #endif
1167    {
1168      ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1169      res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1170    }
1171    if (res)
1172      continue;
1173    if (ptr->count > 0)
1174      ptr->count--;
1175    if (ptr->count == 0 &&
1176        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1177    {
1178      if (last_ptr != NULL)
1179        last_ptr->next = ptr->next;
1180      else
1181        ip_hash_table[hash_index] = ptr->next;
1182
1183      BlockHeapFree(ip_entry_heap, ptr);
1184      ip_entries_count--;
1185      return;
1186    }
1187    last_ptr = ptr;
1188  }
1189 }
1190
1191 /* hash_ip()
1192 *
1193 * input        - pointer to an irc_inaddr
1194 * output       - integer value used as index into hash table
1195 * side effects - hopefully, none
1196 */
1197 static int
1198 hash_ip(struct irc_ssaddr *addr)
1199 {
1200  if (addr->ss.ss_family == AF_INET)
1201  {
1202    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
1203    int hash;
1204    u_int32_t ip;
1205
1206    ip   = ntohl(v4->sin_addr.s_addr);
1207    hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
1208    return hash;
1209  }
1210 #ifdef IPV6
1211  else
1212  {
1213    int hash;
1214    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
1215    u_int32_t *ip = (u_int32_t *)&v6->sin6_addr.s6_addr;
1216
1217    hash  = ip[0] ^ ip[3];
1218    hash ^= hash >> 16;  
1219    hash ^= hash >> 8;  
1220    hash  = hash & (IP_HASH_SIZE - 1);
1221    return hash;
1222  }
1223 #else
1224  return 0;
1225 #endif
1226 }
1227
1228 /* count_ip_hash()
1229 *
1230 * inputs        - pointer to counter of number of ips hashed
1231 *               - pointer to memory used for ip hash
1232 * output        - returned via pointers input
1233 * side effects  - NONE
1234 *
1235 * number of hashed ip #'s is counted up, plus the amount of memory
1236 * used in the hash.
1237 */
1238 void
1239 count_ip_hash(int *number_ips_stored, unsigned long *mem_ips_stored)
1240 {
1241  struct ip_entry *ptr;
1242  int i;
1243
1244  *number_ips_stored = 0;
1245  *mem_ips_stored    = 0;
1246
1247  for (i = 0; i < IP_HASH_SIZE; i++)
1248  {
1249    for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
1250    {
1251      *number_ips_stored += 1;
1252      *mem_ips_stored += sizeof(struct ip_entry);
1253    }
1254  }
1255 }
1256
1257 /* garbage_collect_ip_entries()
1258 *
1259 * input        - NONE
1260 * output       - NONE
1261 * side effects - free up all ip entries with no connections
1262 */
1263 static void
1264 garbage_collect_ip_entries(void)
1265 {
1266  struct ip_entry *ptr;
1267  struct ip_entry *last_ptr;
1268  struct ip_entry *next_ptr;
1269  int i;
1270
1271  for (i = 0; i < IP_HASH_SIZE; i++)
1272  {
1273    last_ptr = NULL;
1274
1275    for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
1276    {
1277      next_ptr = ptr->next;
1278
1279      if (ptr->count == 0 &&
1280          (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1281      {
1282        if (last_ptr != NULL)
1283          last_ptr->next = ptr->next;
1284        else
1285          ip_hash_table[i] = ptr->next;
1286        BlockHeapFree(ip_entry_heap, ptr);
1287        ip_entries_count--;
1288      }
1289      else
1290        last_ptr = ptr;
1291    }
1292  }
1293 }
1294
399   /* detach_conf()
400   *
401   * inputs       - pointer to client to detach
# Line 1300 | 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;
1307 <  struct ConfItem *conf;
1308 <  struct ClassItem *aclass;
1309 <  struct AccessItem *aconf;
1310 <  struct ConfItem *aclass_conf;
1311 <  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;
1316 <
1317 <    if (type == CONF_TYPE || conf->type == type)
1318 <    {
1319 <      dlinkDelete(ptr, &client_p->localClient->confs);
1320 <      free_dlink_node(ptr);
1321 <
1322 <      switch (conf->type)
1323 <      {
1324 <      case CLIENT_TYPE:
1325 <      case OPER_TYPE:
1326 <      case SERVER_TYPE:
1327 <        aconf = map_to_conf(conf);
1328 <
1329 <        assert(aconf->clients > 0);
414 >    struct MaskItem *conf = ptr->data;
415  
416 <        if ((aclass_conf = ClassPtr(aconf)) != NULL)
417 <        {
418 <          aclass = map_to_conf(aclass_conf);
1334 <
1335 <          assert(aclass->curr_user_count > 0);
1336 <
1337 <          if (conf->type == CLIENT_TYPE)
1338 <            remove_from_cidr_check(&client_p->localClient->ip, aclass);
1339 <          if (--aclass->curr_user_count == 0 && aclass->active == 0)
1340 <            delete_conf_item(aclass_conf);
1341 <        }
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 <        if (--aconf->clients == 0 && IsConfIllegal(aconf))
421 <          delete_conf_item(conf);
420 >    if (!(conf->type & type))
421 >      continue;
422  
423 <        break;
423 >    dlinkDelete(ptr, &client_p->connection->confs);
424 >    free_dlink_node(ptr);
425  
426 <      case LEAF_TYPE:
427 <      case HUB_TYPE:
1350 <        match_item = map_to_conf(conf);
1351 <        if (match_item->ref_count == 0 && match_item->illegal)
1352 <          delete_conf_item(conf);
1353 <        break;
1354 <      default:
1355 <        break;
1356 <      }
426 >    if (conf->type == CONF_CLIENT)
427 >      remove_from_cidr_check(&client_p->connection->ip, conf->class);
428  
429 <      if (type != CONF_TYPE)
430 <        return 0;
429 >    if (--conf->class->ref_count == 0 && conf->class->active == 0)
430 >    {
431 >      class_free(conf->class);
432 >      conf->class = NULL;
433      }
1361  }
434  
435 <  return -1;
435 >    if (--conf->ref_count == 0 && conf->active == 0)
436 >      conf_free(conf);
437 >  }
438   }
439  
440   /* attach_conf()
# Line 1374 | 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 <  {
1386 <    struct AccessItem *aconf = map_to_conf(conf);
1387 <    struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1388 <
1389 <    if (IsConfIllegal(aconf))
1390 <      return NOT_AUTHORIZED;
1391 <
1392 <    if (conf->type == CLIENT_TYPE)
1393 <      if (cidr_limit_reached(IsConfExemptLimits(aconf),
1394 <                             &client_p->localClient->ip, aclass))
1395 <        return TOO_MANY;    /* Already at maximum allowed */
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 <    CurrUserCount(aclass)++;
462 <    aconf->clients++;
1399 <  }
1400 <  else if (conf->type == HUB_TYPE || conf->type == LEAF_TYPE)
1401 <  {
1402 <    struct MatchItem *match_item = map_to_conf(conf);
1403 <    match_item->ref_count++;
1404 <  }
461 >  conf->class->ref_count++;
462 >  conf->ref_count++;
463  
464 <  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 1421 | Line 479 | attach_connect_block(struct Client *clie
479                       const char *host)
480   {
481    dlink_node *ptr;
482 <  struct ConfItem *conf;
1425 <  struct AccessItem *aconf;
482 >  struct MaskItem *conf = NULL;
483  
484    assert(client_p != NULL);
485    assert(host != NULL);
# Line 1433 | Line 490 | attach_connect_block(struct Client *clie
490    DLINK_FOREACH(ptr, server_items.head)
491    {
492      conf = ptr->data;
1436    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 1445 | Line 501 | attach_connect_block(struct Client *clie
501    return 0;
502   }
503  
1448 /* find_conf_exact()
1449 *
1450 * inputs       - type of ConfItem
1451 *              - pointer to name to find
1452 *              - pointer to username to find
1453 *              - pointer to host to find
1454 * output       - NULL or pointer to conf found
1455 * side effects - find a conf entry which matches the hostname
1456 *                and has the same name.
1457 */
1458 struct ConfItem *
1459 find_conf_exact(ConfType type, const char *name, const char *user,
1460                const char *host)
1461 {
1462  dlink_node *ptr;
1463  dlink_list *list_p;
1464  struct ConfItem *conf = NULL;
1465  struct AccessItem *aconf;
1466
1467  /* Only valid for OPER_TYPE and ...? */
1468  list_p = map_to_list(type);
1469
1470  DLINK_FOREACH(ptr, (*list_p).head)
1471  {
1472    conf = ptr->data;
1473
1474    if (conf->name == NULL)
1475      continue;
1476    aconf = map_to_conf(conf);
1477    if (aconf->host == NULL)
1478      continue;
1479    if (irccmp(conf->name, name) != 0)
1480      continue;
1481
1482    /*
1483    ** Accept if the *real* hostname (usually sockethost)
1484    ** socket host) matches *either* host or name field
1485    ** of the configuration.
1486    */
1487    if (!match(aconf->host, host) || !match(aconf->user, user))
1488      continue;
1489    if (type == OPER_TYPE)
1490    {
1491      struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1492
1493      if (aconf->clients >= MaxTotal(aclass))
1494        continue;
1495    }
1496
1497    return conf;
1498  }
1499
1500  return NULL;
1501 }
1502
504   /* find_conf_name()
505   *
506   * inputs       - pointer to conf link list to search
# Line 1509 | 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)))
1526 <      return conf;
525 >      if (conf->name && !irccmp(conf->name, name))
526 >        return conf;
527      }
528    }
529  
# Line 1537 | 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:
1545 <    return(&rxconf_items);
1546 <    break;
1547 <  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:
1560 <    return(&class_items);
1561 <    break;
1562 <  case SERVER_TYPE:
558 >  case CONF_SERVER:
559      return(&server_items);
560      break;
561 <  case CLUSTER_TYPE:
561 >  case CONF_SERVICE:
562 >    return(&service_items);
563 >    break;
564 >  case CONF_CLUSTER:
565      return(&cluster_items);
566      break;
1568  case CONF_TYPE:
1569  case GLINE_TYPE:
1570  case KLINE_TYPE:
1571  case DLINE_TYPE:
1572  case CRESV_TYPE:
567    default:
568      return NULL;
569    }
# Line 1581 | 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;
1594 <  struct AccessItem *aconf=NULL;
1595 <  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 <    case RXLINE_TYPE:
593 <      DLINK_FOREACH(ptr, list_p->head)
594 <      {
595 <        conf = ptr->data;
1604 <        assert(conf->regexpname);
592 >  case CONF_SERVICE:
593 >    DLINK_FOREACH(ptr, list_p->head)
594 >    {
595 >      conf = ptr->data;
596  
597 <        if (!ircd_pcre_exec(conf->regexpname, name))
598 <          return conf;
599 <      }
600 <      break;
597 >      if (EmptyString(conf->name))
598 >        continue;
599 >      if ((name != NULL) && !irccmp(name, conf->name))
600 >        return conf;
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  
1618      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;
1639      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 1657 | 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 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;
1670 <  struct MatchItem *match_item;
1671 <  dlink_list *list_p;
1672 <
1673 <  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;
693 <      aconf = (struct AccessItem *)map_to_conf(conf);
693 >
694        if (EmptyString(conf->name))
695 <        continue;
696 <    
697 <      if (irccmp(conf->name, name) == 0)
695 >        continue;
696 >
697 >      if (!irccmp(conf->name, name))
698        {
699 <        if ((user == NULL && (host == NULL)))
700 <          return (conf);
701 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
702 <          return (conf);
703 <        if (match(aconf->user, user) && match(aconf->host, host))
704 <          return (conf);
699 >        if (!who)
700 >          return conf;
701 >        if (EmptyString(conf->user) || EmptyString(conf->host))
702 >          return NULL;
703 >        if (!match(conf->user, who->username))
704 >        {
705 >          switch (conf->htype)
706 >          {
707 >            case HM_HOST:
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->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;
718 >            case HM_IPV6:
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;
724 >            default:
725 >              assert(0);
726 >          }
727 >        }
728        }
729      }
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 <      {
1738 <          return (conf);
1739 <      }
749 >        return conf;
750      }
1741    break;
751  
1743  case CLASS_TYPE:
1744    DLINK_FOREACH(ptr, list_p->head)
1745    {
1746      conf = ptr->data;
1747      if (EmptyString(conf->name))
1748        continue;
1749    
1750      if (irccmp(conf->name, name) == 0)
1751        return (conf);
1752    }
752      break;
753  
754    default:
755      break;
756    }
757 <  return(NULL);
757 >
758 >  return NULL;
759   }
760  
761   /* rehash()
# Line 1767 | 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  
1774 #ifndef _WIN32
774    restart_resolver();
1776 #endif
1777  /* don't close listeners until we know we can go ahead with the rehash */
775  
776 <  /* Check to see if we magically got(or lost) IPv6 support */
1780 <  check_can_use_v6();
776 >  /* don't close listeners until we know we can go ahead with the rehash */
777  
778    read_conf_files(0);
779  
1784  if (ServerInfo.description != NULL)
1785    strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1786
1787 #ifndef STATIC_MODULES
780    load_conf_modules();
781 < #endif
1790 <
1791 <  flush_deleted_I_P();
1792 <
1793 <  rehashed_klines = 1;
781 >  check_conf_klines();
782  
783 <  if (ConfigLoggingEntry.use_logging)
1796 <    reopen_log(logFileName);
1797 <
1798 <  return(0);
783 >  return 0;
784   }
785  
786   /* set_default_conf()
# Line 1813 | 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 <  /* Don't reset hub, as that will break lazylinks */
836 <  /* ServerInfo.hub = NO; */
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;
842 <
843 <  set_log_level(L_NOTICE);
844 <  ConfigLoggingEntry.use_logging = 1;
845 <  ConfigLoggingEntry.operlog[0] = '\0';
846 <  ConfigLoggingEntry.userlog[0] = '\0';
847 <  ConfigLoggingEntry.klinelog[0] = '\0';
848 <  ConfigLoggingEntry.glinelog[0] = '\0';
849 <  ConfigLoggingEntry.killlog[0] = '\0';
850 <  ConfigLoggingEntry.operspylog[0] = '\0';
851 <  ConfigLoggingEntry.ioerrlog[0] = '\0';
1852 <  ConfigLoggingEntry.failed_operlog[0] = '\0';
1853 <
1854 <  ConfigChannel.disable_fake_channels = NO;
1855 <  ConfigChannel.restrict_channels = NO;
1856 <  ConfigChannel.disable_local_channels = NO;
1857 <  ConfigChannel.use_invex = YES;
1858 <  ConfigChannel.use_except = YES;
1859 <  ConfigChannel.use_knock = YES;
1860 <  ConfigChannel.knock_delay = 300;
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_del_all();
844 >
845 >  ConfigLog.use_logging = 1;
846 >
847 >  ConfigChannel.disable_fake_channels = 0;
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;
1863 <  ConfigChannel.quiet_on_ban = YES;
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 = NO;
858 <  ConfigChannel.no_create_on_split = NO;
1869 <  ConfigChannel.burst_topicwho = YES;
857 >  ConfigChannel.no_join_on_split = 0;
858 >  ConfigChannel.no_create_on_split = 0;
859  
860 <  ConfigServerHide.flatten_links = NO;
860 >  ConfigServerHide.flatten_links = 0;
861    ConfigServerHide.links_delay = 300;
862 <  ConfigServerHide.hidden = NO;
863 <  ConfigServerHide.disable_hidden = NO;
864 <  ConfigServerHide.hide_servers = NO;
865 <  DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
866 <  ConfigServerHide.hide_server_ips = NO;
867 <
868 <  ConfigFileEntry.gline_min_cidr = 16;
869 <  ConfigFileEntry.gline_min_cidr6 = 48;
870 <  ConfigFileEntry.invisible_on_connect = YES;
871 <  ConfigFileEntry.burst_away = NO;
872 <  ConfigFileEntry.use_whois_actually = YES;
873 <  ConfigFileEntry.tkline_expire_notices = YES;
874 <  ConfigFileEntry.hide_spoof_ips = YES;
875 <  ConfigFileEntry.ignore_bogus_ts = NO;
876 <  ConfigFileEntry.disable_auth = NO;
877 <  ConfigFileEntry.disable_remote = NO;
878 <  ConfigFileEntry.kill_chase_time_limit = 90;
879 <  ConfigFileEntry.default_floodcount = 8; /* XXX */
880 <  ConfigFileEntry.failed_oper_notice = YES;
881 <  ConfigFileEntry.dots_in_ident = 0;      /* XXX */
882 <  ConfigFileEntry.dot_in_ip6_addr = YES;
883 <  ConfigFileEntry.min_nonwildcard = 4;
884 <  ConfigFileEntry.min_nonwildcard_simple = 3;
885 <  ConfigFileEntry.max_accept = 20;
886 <  ConfigFileEntry.anti_nick_flood = NO;   /* XXX */
887 <  ConfigFileEntry.max_nick_time = 20;
888 <  ConfigFileEntry.max_nick_changes = 5;
889 <  ConfigFileEntry.anti_spam_exit_message_time = 0;  /* XXX */
890 <  ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
891 <  ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;  /* XXX */
892 <  ConfigFileEntry.kline_with_reason = YES;
893 <  ConfigFileEntry.kline_reason = NULL;
894 <  ConfigFileEntry.warn_no_nline = YES;
895 <  ConfigFileEntry.stats_o_oper_only = NO; /* XXX */
896 <  ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
897 <  ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
898 <  ConfigFileEntry.stats_P_oper_only = NO;
899 <  ConfigFileEntry.caller_id_wait = 60;
900 <  ConfigFileEntry.opers_bypass_callerid = NO;
901 <  ConfigFileEntry.pace_wait = 10;
902 <  ConfigFileEntry.pace_wait_simple = 1;
903 <  ConfigFileEntry.short_motd = NO;
904 <  ConfigFileEntry.ping_cookie = NO;
905 <  ConfigFileEntry.no_oper_flood = NO;     /* XXX */
906 <  ConfigFileEntry.true_no_oper_flood = NO;  /* XXX */
907 <  ConfigFileEntry.oper_pass_resv = YES;
908 <  ConfigFileEntry.glines = NO;            /* XXX */
909 <  ConfigFileEntry.gline_time = 12 * 3600; /* XXX */
910 <  ConfigFileEntry.idletime = 0;
911 <  ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
912 <  ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
913 <  ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;  /* XXX */
914 <  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
915 <    UMODE_OPERWALL | UMODE_WALLOP;        /* XXX */
916 <  DupString(ConfigFileEntry.servlink_path, SLPATH);
917 < #ifdef HAVE_LIBCRYPTO
918 <  /* jdc -- This is our default value for a cipher.  According to the
919 <   *        CRYPTLINK document (doc/cryptlink.txt), BF/128 must be supported
920 <   *        under all circumstances if cryptlinks are enabled.  So,
921 <   *        this will be our default.
922 <   *
923 <   *        NOTE: I apologise for the hard-coded value of "1" (BF/128).
924 <   *              This should be moved into a find_cipher() routine.
925 <   */
926 <  ConfigFileEntry.default_cipher_preference = &CipherTable[1];
927 < #endif
928 <  ConfigFileEntry.use_egd = NO;
929 <  ConfigFileEntry.egdpool_path = NULL;
930 < #ifdef HAVE_LIBZ
931 <  ConfigFileEntry.compression_level = 0;
932 < #endif
933 <  ConfigFileEntry.throttle_time = 10;
862 >  ConfigServerHide.hidden = 0;
863 >  ConfigServerHide.hide_servers = 0;
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 >  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 (ConfigGeneral.ts_warn_delta < TS_WARN_DELTA_MIN)
923 >    ConfigGeneral.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
924 >
925 >  if (ConfigGeneral.ts_max_delta < TS_MAX_DELTA_MIN)
926 >    ConfigGeneral.ts_max_delta = TS_MAX_DELTA_DEFAULT;
927 >
928 >  if (ConfigServerInfo.network_name == NULL)
929 >    ConfigServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
930 >
931 >  if (ConfigServerInfo.network_desc == NULL)
932 >    ConfigServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
933 >
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
941   * side effects - Read configuration file.
942   */
943   static void
944 < read_conf(FBFILE *file)
944 > read_conf(FILE *file)
945   {
946    lineno = 0;
947  
948 <  set_default_conf(); /* Set default values prior to conf parsing */
949 <  ypass = 1;
950 <  yyparse();          /* pick up the classes first */
951 <
952 <  fbrewind(file);
953 <
954 <  ypass = 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 */
1969 < }
1970 <
1971 < static void
1972 < validate_conf(void)
1973 < {
1974 <  if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1975 <    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1976 <
1977 <  if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1978 <    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1979 <
1980 <  if (ConfigFileEntry.servlink_path == NULL)
1981 <    DupString(ConfigFileEntry.servlink_path, SLPATH);
1982 <
1983 <  if (ServerInfo.network_name == NULL)
1984 <    DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1985 <
1986 <  if (ServerInfo.network_desc == NULL)
1987 <    DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1988 <
1989 <  if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1990 <      (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1991 <    ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
948 >  set_default_conf();  /* Set default values prior to conf parsing */
949 >  conf_parser_ctx.pass = 1;
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 >  class_delete_marked();  /* Delete unused classes that are marked for deletion */
959   }
960  
961   /* lookup_confhost()
# Line 1996 | Line 963 | validate_conf(void)
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   {
2002  struct AccessItem *aconf;
969    struct addrinfo hints, *res;
970  
971 <  aconf = map_to_conf(conf);
972 <
2007 <  if (EmptyString(aconf->host) ||
2008 <      EmptyString(aconf->user))
2009 <  {
2010 <    ilog(L_ERROR, "Host/server name error: (%s) (%s)",
2011 <         aconf->host, conf->name);
2012 <    return;
2013 <  }
2014 <
2015 <  if (strchr(aconf->host, '*') ||
2016 <      strchr(aconf->host, '?'))
2017 <    return;
2018 <
2019 <  /* 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 2027 | 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 (irc_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(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
992 <  aconf->ipnum.ss_len = res->ai_addrlen;
993 <  aconf->ipnum.ss.ss_family = res->ai_family;
994 <  irc_freeaddrinfo(res);
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 >
995 >  freeaddrinfo(res);
996   }
997  
998   /* conf_connect_allowed()
# Line 2051 | 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) <
2067 <      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  
2077 static struct AccessItem *
2078 find_regexp_kline(const char *uhi[])
2079 {
2080  const dlink_node *ptr = NULL;
2081
2082  DLINK_FOREACH(ptr, rkconf_items.head)
2083  {
2084    struct AccessItem *aptr = map_to_conf(ptr->data);
2085
2086    assert(aptr->regexuser);
2087    assert(aptr->regexhost);
2088
2089    if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2090        (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2091         !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2092      return aptr;
2093  }
2094
2095  return NULL;
2096 }
2097
2098 /* find_kill()
2099 *
2100 * inputs       - pointer to client structure
2101 * output       - pointer to struct AccessItem if found
2102 * side effects - See if this user is klined already,
2103 *                and if so, return struct AccessItem pointer
2104 */
2105 struct AccessItem *
2106 find_kill(struct Client *client_p)
2107 {
2108  struct AccessItem *aconf = NULL;
2109  const char *uhi[3];
2110
2111  uhi[0] = client_p->username;
2112  uhi[1] = client_p->host;
2113  uhi[2] = client_p->sockhost;
2114
2115  assert(client_p != NULL);
2116
2117  aconf = find_kline_conf(client_p->host, client_p->username,
2118                          &client_p->localClient->ip,
2119                          client_p->localClient->aftype);
2120  if (aconf == NULL)
2121    aconf = find_regexp_kline(uhi);
2122
2123  if (aconf && (aconf->status & CONF_KLINE))
2124    return aconf;
2125
2126  return NULL;
2127 }
2128
2129 struct AccessItem *
2130 find_gline(struct Client *client_p)
2131 {
2132  struct AccessItem *aconf;
2133
2134  assert(client_p != NULL);
2135
2136  aconf = find_gline_conf(client_p->host, client_p->username,
2137                          &client_p->localClient->ip,
2138                          client_p->localClient->aftype);
2139
2140  if (aconf && (aconf->status & CONF_GLINE))
2141    return aconf;
2142
2143  return NULL;
2144 }
2145
2146 /* add_temp_line()
2147 *
2148 * inputs        - pointer to struct ConfItem
2149 * output        - none
2150 * Side effects  - links in given struct ConfItem into
2151 *                 temporary *line link list
2152 */
2153 void
2154 add_temp_line(struct ConfItem *conf)
2155 {
2156  struct AccessItem *aconf;
2157
2158  if (conf->type == DLINE_TYPE)
2159  {
2160    aconf = map_to_conf(conf);
2161    SetConfTemporary(aconf);
2162    dlinkAdd(conf, &conf->node, &temporary_dlines);
2163    MyFree(aconf->user);
2164    aconf->user = NULL;
2165    add_conf_by_address(CONF_DLINE, aconf);
2166  }
2167  else if (conf->type == KLINE_TYPE)
2168  {
2169    aconf = map_to_conf(conf);
2170    SetConfTemporary(aconf);
2171    dlinkAdd(conf, &conf->node, &temporary_klines);
2172    add_conf_by_address(CONF_KILL, aconf);
2173  }
2174  else if (conf->type == GLINE_TYPE)
2175  {
2176    aconf = map_to_conf(conf);
2177    SetConfTemporary(aconf);
2178    dlinkAdd(conf, &conf->node, &temporary_glines);
2179    add_conf_by_address(CONF_GLINE, aconf);
2180  }
2181  else if (conf->type == XLINE_TYPE)
2182  {
2183    conf->flags |= CONF_FLAGS_TEMPORARY;
2184    dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2185  }
2186  else if (conf->type == RXLINE_TYPE)
2187  {
2188    conf->flags |= CONF_FLAGS_TEMPORARY;
2189    dlinkAdd(conf, make_dlink_node(), &temporary_rxlines);
2190  }
2191  else if (conf->type == RKLINE_TYPE)
2192  {
2193    conf->flags |= CONF_FLAGS_TEMPORARY;
2194    dlinkAdd(conf, make_dlink_node(), &temporary_rklines);
2195  }
2196  else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2197  {
2198    conf->flags |= CONF_FLAGS_TEMPORARY;
2199    dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2200  }
2201 }
2202
1034   /* cleanup_tklines()
1035   *
1036   * inputs       - NONE
# Line 2208 | 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 <  expire_tklines(&temporary_glines);
1045 <  expire_tklines(&temporary_klines);
1046 <  expire_tklines(&temporary_dlines);
1047 <  expire_tklines(&temporary_xlines);
2217 <  expire_tklines(&temporary_rxlines);
2218 <  expire_tklines(&temporary_rklines);
2219 <  expire_tklines(&temporary_resv);
1044 >  hostmask_expire_temporary();
1045 >  expire_tklines(&xconf_items);
1046 >  expire_tklines(&nresv_items);
1047 >  expire_tklines(&cresv_items);
1048   }
1049  
1050   /* expire_tklines()
# Line 2228 | 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;
2233 <  struct ConfItem *conf;
2234 <  struct MatchItem *xconf;
2235 <  struct MatchItem *nconf;
2236 <  struct AccessItem *aconf;
2237 <  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;
2242    if (conf->type == GLINE_TYPE ||
2243        conf->type == KLINE_TYPE ||
2244        conf->type == DLINE_TYPE)
2245    {
2246      aconf = (struct AccessItem *)map_to_conf(conf);
2247      if (aconf->hold <= CurrentTime)
2248      {
2249        /* XXX - Do we want GLINE expiry notices?? */
2250        /* Alert opers that a TKline expired - Hwy */
2251        if (ConfigFileEntry.tkline_expire_notices)
2252        {
2253          if (aconf->status & CONF_KILL)
2254          {
2255            sendto_realops_flags(UMODE_ALL, L_ALL,
2256                                 "Temporary K-line for [%s@%s] expired",
2257                                 (aconf->user) ? aconf->user : "*",
2258                                 (aconf->host) ? aconf->host : "*");
2259          }
2260          else if (conf->type == DLINE_TYPE)
2261          {
2262            sendto_realops_flags(UMODE_ALL, L_ALL,
2263                                 "Temporary D-line for [%s] expired",
2264                                 (aconf->host) ? aconf->host : "*");
2265          }
2266        }
1065  
1066 <        dlinkDelete(ptr, tklist);
1067 <        delete_one_address_conf(aconf->host, aconf);
1068 <      }
1069 <    }
2272 <    else if (conf->type == XLINE_TYPE ||
2273 <             conf->type == RXLINE_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)
2279 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2280 <                               "Temporary X-line for [%s] %sexpired", conf->name,
2281 <                               conf->type == RXLINE_TYPE ? "(REGEX) " : "");
2282 <        dlinkDelete(ptr, tklist);
2283 <        free_dlink_node(ptr);
2284 <        delete_conf_item(conf);
2285 <      }
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 == RKLINE_TYPE)
1076 >    else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1077      {
1078 <      aconf = map_to_conf(conf);
1079 <      if (aconf->hold <= CurrentTime)
2291 <      {
2292 <        if (ConfigFileEntry.tkline_expire_notices)
2293 <           sendto_realops_flags(UMODE_ALL, L_ALL,
2294 <                                "Temporary K-line for [%s@%s] (REGEX) expired",
2295 <                                (aconf->user) ? aconf->user : "*",
2296 <                                (aconf->host) ? aconf->host : "*");
2297 <        dlinkDelete(ptr, tklist);
2298 <        free_dlink_node(ptr);
2299 <        delete_conf_item(conf);
2300 <      }
2301 <    }
2302 <    else if (conf->type == NRESV_TYPE)
2303 <    {
2304 <      nconf = (struct MatchItem *)map_to_conf(conf);
2305 <      if (nconf->hold <= CurrentTime)
2306 <      {
2307 <        if (ConfigFileEntry.tkline_expire_notices)
2308 <          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);
2311 <        free_dlink_node(ptr);
2312 <        delete_conf_item(conf);
2313 <      }
2314 <    }
2315 <    else if (conf->type == CRESV_TYPE)
2316 <    {
2317 <      cconf = (struct ResvChannel *)map_to_conf(conf);
2318 <      if (cconf->hold <= CurrentTime)
2319 <      {
2320 <        if (ConfigFileEntry.tkline_expire_notices)
2321 <          sendto_realops_flags(UMODE_ALL, L_ALL,
2322 <                               "Temporary RESV for [%s] expired", cconf->name);
2323 <        delete_channel_resv(cconf);
2324 <      }
1081 >      conf_free(conf);
1082      }
1083    }
1084   }
# Line 2334 | Line 1091 | expire_tklines(dlink_list *tklist)
1091   */
1092   static const struct oper_privs
1093   {
1094 <  const unsigned int oprivs;
2338 <  const unsigned int hidden;
1094 >  const unsigned int flag;
1095    const unsigned char c;
1096   } flag_list[] = {
1097 <  { OPER_FLAG_ADMIN,       OPER_FLAG_HIDDEN_ADMIN,  'A' },
1098 <  { OPER_FLAG_REMOTEBAN,   0,                       'B' },
1099 <  { OPER_FLAG_DIE,         0,                       'D' },
1100 <  { OPER_FLAG_GLINE,       0,                       'G' },
1101 <  { OPER_FLAG_REHASH,      0,                       'H' },
1102 <  { OPER_FLAG_K,           0,                       'K' },
1103 <  { OPER_FLAG_OPERWALL,    0,                       'L' },
1104 <  { OPER_FLAG_N,           0,                       'N' },
1105 <  { OPER_FLAG_GLOBAL_KILL, 0,                       'O' },
1106 <  { OPER_FLAG_REMOTE,      0,                       'R' },
1107 <  { OPER_FLAG_OPER_SPY,    0,                       'S' },
1108 <  { OPER_FLAG_UNKLINE,     0,                       'U' },
1109 <  { OPER_FLAG_X,           0,                       'X' },
1110 <  { 0, 0, '\0' }
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;
2362  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 <        (port & flag_list[i].hidden) == 0)
2368 <      *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 2376 | 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.
1138   */
1139 < char *
1139 > const char *
1140   get_oper_name(const struct Client *client_p)
1141   {
1142 <  dlink_node *cnode;
2388 <  struct ConfItem *conf;
2389 <  struct AccessItem *aconf;
2390 <
1142 >  const dlink_node *cnode = NULL;
1143    /* +5 for !,@,{,} and null */
1144 <  static char buffer[NICKLEN+USERLEN+HOSTLEN+HOSTLEN+5];
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 <    DLINK_FOREACH(cnode, client_p->localClient->confs.head)
1151 >    if ((cnode = client_p->connection->confs.head))
1152      {
1153 <      conf = cnode->data;
2399 <      aconf = map_to_conf(conf);
1153 >      const struct MaskItem *conf = cnode->data;
1154  
1155 <      if (IsConfOperator(aconf))
1155 >      if (IsConfOperator(conf))
1156        {
1157 <        ircsprintf(buffer, "%s!%s@%s{%s}", client_p->name,
1158 <                   client_p->username, client_p->host,
1159 <                   conf->name);
2406 <        return buffer;
1157 >        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1158 >                 client_p->username, client_p->host, conf->name);
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 <  ircsprintf(buffer, "%s!%s@%s{%s}", client_p->name,
1171 <             client_p->username, client_p->host, client_p->servptr->name);
1170 >  snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1171 >           client_p->username, client_p->host, client_p->servptr->name);
1172    return buffer;
1173   }
1174  
# Line 2427 | 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 <  filename = get_conf_name(CONF_TYPE);
1188 >  conf_parser_ctx.boot = cold;
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  
1199 <  if ((conf_fbfile_in = fbopen(filename, "r")) == NULL)
1199 >  if ((conf_parser_ctx.conf_file = fopen(filename, "r")) == NULL)
1200    {
1201      if (cold)
1202      {
1203 <      ilog(L_CRIT, "Unable to read configuration file '%s': %s",
1203 >      ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
1204             filename, strerror(errno));
1205        exit(-1);
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 2461 | Line 1216 | read_conf_files(int cold)
1216    if (!cold)
1217      clear_out_old_conf();
1218  
1219 <  read_conf(conf_fbfile_in);
1220 <  fbclose(conf_fbfile_in);
1219 >  read_conf(conf_parser_ctx.conf_file);
1220 >  fclose(conf_parser_ctx.conf_file);
1221 >
1222 >  log_reopen_all();
1223 >
1224 >  add_isupport("NICKLEN", NULL, ConfigServerInfo.max_nick_length);
1225 >  add_isupport("NETWORK", ConfigServerInfo.network_name, -1);
1226  
1227 <  add_isupport("NETWORK", ServerInfo.network_name, -1);
2468 <  ircsprintf(chanmodes, "b%s%s:%d", ConfigChannel.use_except ? "e" : "",
2469 <             ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
1227 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1228    add_isupport("MAXLIST", chanmodes, -1);
1229 <  add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1230 <  if (ConfigChannel.disable_local_channels)
1231 <    add_isupport("CHANTYPES", "#", -1);
1232 <  else
1233 <    add_isupport("CHANTYPES", "#&", -1);
2476 <  ircsprintf(chanlimit, "%s:%d", ConfigChannel.disable_local_channels ? "#" : "#&",
2477 <             ConfigChannel.max_chans_per_user);
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 <  ircsprintf(chanmodes, "%s%s%s", ConfigChannel.use_except ? "e" : "",
1236 <             ConfigChannel.use_invex ? "I" : "", "b,k,l,imnpst");
1237 <  add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2482 <  if (ConfigChannel.use_except)
2483 <    add_isupport("EXCEPTS", "e", -1);
2484 <  if (ConfigChannel.use_invex)
2485 <    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 2490 | Line 1242 | read_conf_files(int cold)
1242     * on strlen(form_str(RPL_ISUPPORT))
1243     */
1244    rebuild_isupport_message_line();
2493
2494  parse_conf_file(KLINE_TYPE, cold);
2495  parse_conf_file(RKLINE_TYPE, cold);
2496  parse_conf_file(DLINE_TYPE, cold);
2497  parse_conf_file(XLINE_TYPE, cold);
2498  parse_conf_file(RXLINE_TYPE, cold);
2499  parse_conf_file(NRESV_TYPE, cold);
2500  parse_conf_file(CRESV_TYPE, cold);
2501 }
2502
2503 /* parse_conf_file()
2504 *
2505 * inputs       - type of conf file to parse
2506 * output       - none
2507 * side effects - conf file for givenconf type is opened and read then parsed
2508 */
2509 static void
2510 parse_conf_file(int type, int cold)
2511 {
2512  FBFILE *file = NULL;
2513  const char *filename = get_conf_name(type);
2514
2515  if ((file = fbopen(filename, "r")) == NULL)
2516  {
2517    if (cold)
2518      ilog(L_ERROR, "Unable to read configuration file '%s': %s",
2519           filename, strerror(errno));
2520    else
2521      sendto_realops_flags(UMODE_ALL, L_ALL,
2522                    "Unable to read configuration file '%s': %s",
2523                           filename, strerror(errno));
2524  }
2525  else
2526  {
2527    parse_csv_file(file, type);
2528    fbclose(file);
2529  }
1245   }
1246  
1247   /* clear_out_old_conf()
# Line 2539 | Line 1254 | static void
1254   clear_out_old_conf(void)
1255   {
1256    dlink_node *ptr = NULL, *next_ptr = NULL;
2542  struct ConfItem *conf;
2543  struct AccessItem *aconf;
2544  struct ClassItem *cltmp;
2545  struct MatchItem *match_item;
1257    dlink_list *free_items [] = {
1258 <    &server_items,   &oconf_items,    &hub_items, &leaf_items,
1259 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1260 <     &nresv_items, &cluster_items,  &gdeny_items, NULL
1258 >    &server_items,   &oconf_items,
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 2554 | 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;
2563 <      /* XXX This is less than pretty */
2564 <      if (conf->type == SERVER_TYPE)
2565 <      {
2566 <        aconf = map_to_conf(conf);
1273 >      struct MaskItem *conf = ptr->data;
1274  
1275 <        if (aconf->clients != 0)
1276 <        {
2570 <          SetConfIllegal(aconf);
2571 <          dlinkDelete(&conf->node, &server_items);
2572 <        }
2573 <        else
2574 <        {
2575 <          delete_conf_item(conf);
2576 <        }
2577 <      }
2578 <      else if (conf->type == OPER_TYPE)
2579 <      {
2580 <        aconf = map_to_conf(conf);
1275 >      conf->active = 0;
1276 >      dlinkDelete(&conf->node, *iterator);
1277  
1278 <        if (aconf->clients != 0)
1279 <        {
2584 <          SetConfIllegal(aconf);
2585 <          dlinkDelete(&conf->node, &oconf_items);
2586 <        }
2587 <        else
2588 <        {
2589 <          delete_conf_item(conf);
2590 <        }
2591 <      }
2592 <      else if (conf->type == CLIENT_TYPE)
1278 >      /* XXX This is less than pretty */
1279 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1280        {
1281 <        aconf = map_to_conf(conf);
1282 <
2596 <        if (aconf->clients != 0)
2597 <        {
2598 <          SetConfIllegal(aconf);
2599 <        }
2600 <        else
2601 <        {
2602 <          delete_conf_item(conf);
2603 <        }
1281 >        if (!conf->ref_count)
1282 >          conf_free(conf);
1283        }
1284 <      else if (conf->type == XLINE_TYPE  ||
2606 <               conf->type == RXLINE_TYPE ||
2607 <               conf->type == RKLINE_TYPE)
1284 >      else if (conf->type == CONF_XLINE)
1285        {
1286 <        /* temporary (r)xlines are also on
1287 <         * the (r)xconf items list */
2611 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2612 <          continue;
2613 <
2614 <        delete_conf_item(conf);
1286 >        if (!conf->until)
1287 >          conf_free(conf);
1288        }
1289        else
1290 <      {
2618 <        if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2619 <        {
2620 <          match_item = map_to_conf(conf);
2621 <          if (match_item->ref_count <= 0)
2622 <            delete_conf_item(conf);
2623 <          else
2624 <          {
2625 <            match_item->illegal = 1;
2626 <            dlinkDelete(&conf->node, *iterator);
2627 <          }
2628 <        }
2629 <        else
2630 <          delete_conf_item(conf);
2631 <      }
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)
2640 <  {
2641 <    cltmp = map_to_conf(ptr->data);
2642 <
2643 <    if (ptr != class_items.tail)  /* never mark the "default" class */
2644 <      cltmp->active = 0;
2645 <  }
1300 >  class_mark_for_deletion();
1301  
1302    clear_out_address_conf();
1303  
1304    /* clean out module paths */
2650 #ifndef STATIC_MODULES
1305    mod_clear_paths();
2652 #endif
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;
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  
2677  /* clean out AdminInfo */
2678  MyFree(AdminInfo.name);
2679  AdminInfo.name = NULL;
2680  MyFree(AdminInfo.email);
2681  AdminInfo.email = NULL;
2682  MyFree(AdminInfo.description);
2683  AdminInfo.description = NULL;
2684
2685  /* operator{} and class{} blocks are freed above */
1335    /* clean out listeners */
1336    close_listeners();
2688
2689  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2690   * exempt{} and gecos{} blocks are freed above too
2691   */
2692
2693  /* clean out general */
2694  MyFree(ConfigFileEntry.servlink_path);
2695  ConfigFileEntry.servlink_path = NULL;
2696 #ifdef HAVE_LIBCRYPTO
2697  ConfigFileEntry.default_cipher_preference = NULL;
2698 #endif /* HAVE_LIBCRYPTO */
2699  delete_isupport("INVEX");
2700  delete_isupport("EXCEPTS");
2701 }
2702
2703 /* flush_deleted_I_P()
2704 *
2705 * inputs       - none
2706 * output       - none
2707 * side effects - This function removes I/P conf items
2708 */
2709 static void
2710 flush_deleted_I_P(void)
2711 {
2712  dlink_node *ptr;
2713  dlink_node *next_ptr;
2714  struct ConfItem *conf;
2715  struct AccessItem *aconf;
2716  dlink_list * free_items [] = {
2717    &server_items, &oconf_items, NULL
2718  };
2719  dlink_list ** iterator = free_items; /* C is dumb */
2720
2721  /* flush out deleted I and P lines
2722   * although still in use.
2723   */
2724  for (; *iterator != NULL; iterator++)
2725  {
2726    DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2727    {
2728      conf = ptr->data;
2729      aconf = (struct AccessItem *)map_to_conf(conf);
2730
2731      if (IsConfIllegal(aconf))
2732      {
2733        dlinkDelete(ptr, *iterator);
2734
2735        if (aconf->clients == 0)
2736          delete_conf_item(conf);
2737      }
2738    }
2739  }
2740 }
2741
2742 /* get_conf_name()
2743 *
2744 * inputs       - type of conf file to return name of file for
2745 * output       - pointer to filename for type of conf
2746 * side effects - none
2747 */
2748 const char *
2749 get_conf_name(ConfType type)
2750 {
2751  switch (type)
2752  {
2753    case CONF_TYPE:
2754      return ConfigFileEntry.configfile;
2755      break;
2756    case KLINE_TYPE:
2757      return ConfigFileEntry.klinefile;
2758      break;
2759    case RKLINE_TYPE:
2760      return ConfigFileEntry.rklinefile;
2761      break;
2762    case DLINE_TYPE:
2763      return ConfigFileEntry.dlinefile;
2764      break;
2765    case XLINE_TYPE:
2766      return ConfigFileEntry.xlinefile;
2767      break;
2768    case RXLINE_TYPE:
2769      return ConfigFileEntry.rxlinefile;
2770      break;
2771    case CRESV_TYPE:
2772      return ConfigFileEntry.cresvfile;
2773      break;
2774    case NRESV_TYPE:
2775      return ConfigFileEntry.nresvfile;
2776      break;
2777    case GLINE_TYPE:
2778      return ConfigFileEntry.glinefile;
2779      break;
2780
2781    default:
2782      return NULL;  /* This should NEVER HAPPEN since we call this function
2783                       only with the above values, this will cause us to core
2784                       at some point if this happens so we know where it was */
2785  }
2786 }
2787
2788 #define BAD_PING (-1)
2789
2790 /* get_conf_ping()
2791 *
2792 * inputs       - pointer to struct AccessItem
2793 *              - pointer to a variable that receives ping warning time
2794 * output       - ping frequency
2795 * side effects - NONE
2796 */
2797 static int
2798 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2799 {
2800  struct ClassItem *aclass;
2801  struct AccessItem *aconf;
2802
2803  if (conf != NULL)
2804  {
2805    aconf = (struct AccessItem *)map_to_conf(conf);
2806    if (aconf->class_ptr != NULL)
2807    {
2808      aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2809      *pingwarn = PingWarning(aclass);
2810      return PingFreq(aclass);
2811    }
2812  }
2813
2814  return BAD_PING;
2815 }
2816
2817 /* get_client_class()
2818 *
2819 * inputs       - pointer to client struct
2820 * output       - pointer to name of class
2821 * side effects - NONE
2822 */
2823 const char *
2824 get_client_class(struct Client *target_p)
2825 {
2826  dlink_node *ptr;
2827  struct ConfItem *conf;
2828  struct AccessItem *aconf;
2829
2830  if (target_p != NULL && !IsMe(target_p) &&
2831      target_p->localClient->confs.head != NULL)
2832  {
2833    DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2834    {
2835      conf = ptr->data;
2836
2837      if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2838          conf->type == OPER_TYPE)
2839      {
2840        aconf = (struct AccessItem *) map_to_conf(conf);
2841        if (aconf->class_ptr != NULL)
2842          return aconf->class_ptr->name;
2843      }
2844    }
2845  }
2846
2847  return "default";
2848 }
2849
2850 /* get_client_ping()
2851 *
2852 * inputs       - pointer to client struct
2853 *              - pointer to a variable that receives ping warning time
2854 * output       - ping frequency
2855 * side effects - NONE
2856 */
2857 int
2858 get_client_ping(struct Client *target_p, int *pingwarn)
2859 {
2860  int ping;
2861  struct ConfItem *conf;
2862  dlink_node *nlink;
2863
2864  if (target_p->localClient->confs.head != NULL)
2865    DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2866    {
2867      conf = nlink->data;
2868
2869      if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2870          (conf->type == OPER_TYPE))
2871      {
2872        ping = get_conf_ping(conf, pingwarn);
2873        if (ping > 0)
2874          return ping;
2875      }
2876    }
2877
2878  *pingwarn = 0;
2879  return DEFAULT_PINGFREQUENCY;
2880 }
2881
2882 /* find_class()
2883 *
2884 * inputs       - string name of class
2885 * output       - corresponding Class pointer
2886 * side effects - NONE
2887 */
2888 struct ConfItem *
2889 find_class(const char *classname)
2890 {
2891  struct ConfItem *conf;
2892
2893  if ((conf = find_exact_name_conf(CLASS_TYPE, classname, NULL, NULL)) != NULL)
2894    return conf;
2895
2896  return class_default;
2897 }
2898
2899 /* check_class()
2900 *
2901 * inputs       - NONE
2902 * output       - NONE
2903 * side effects -
2904 */
2905 void
2906 check_class(void)
2907 {
2908  dlink_node *ptr = NULL, *next_ptr = NULL;
2909
2910  DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2911  {
2912    struct ClassItem *aclass = map_to_conf(ptr->data);
2913
2914    if (!aclass->active && !CurrUserCount(aclass))
2915    {
2916      destroy_cidr_class(aclass);
2917      delete_conf_item(ptr->data);
2918    }
2919  }
2920 }
2921
2922 /* init_class()
2923 *
2924 * inputs       - NONE
2925 * output       - NONE
2926 * side effects -
2927 */
2928 void
2929 init_class(void)
2930 {
2931  struct ClassItem *aclass;
2932
2933  class_default = make_conf_item(CLASS_TYPE);
2934
2935  aclass = map_to_conf(class_default);
2936  aclass->active = 1;
2937  DupString(class_default->name, "default");
2938  ConFreq(aclass)  = DEFAULT_CONNECTFREQUENCY;
2939  PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
2940  MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
2941  MaxSendq(aclass) = DEFAULT_SENDQ;
2942
2943  client_check_cb = register_callback("check_client", check_client);
2944 }
2945
2946 /* get_sendq()
2947 *
2948 * inputs       - pointer to client
2949 * output       - sendq for this client as found from its class
2950 * side effects - NONE
2951 */
2952 unsigned long
2953 get_sendq(struct Client *client_p)
2954 {
2955  unsigned long sendq = DEFAULT_SENDQ;
2956  dlink_node *ptr;
2957  struct ConfItem *conf;
2958  struct ConfItem *class_conf;
2959  struct ClassItem *aclass;
2960  struct AccessItem *aconf;
2961
2962  if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2963  {
2964    DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2965    {
2966      conf = ptr->data;
2967      if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2968          || (conf->type == CLIENT_TYPE))
2969      {
2970        aconf = (struct AccessItem *)map_to_conf(conf);
2971        if ((class_conf = aconf->class_ptr) == NULL)
2972          continue;
2973        aclass = (struct ClassItem *)map_to_conf(class_conf);
2974        sendq = MaxSendq(aclass);
2975        return sendq;
2976      }
2977    }
2978  }
2979  /* XXX return a default?
2980   * if here, then there wasn't an attached conf with a sendq
2981   * that is very bad -Dianora
2982   */
2983  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);
2996 <  struct ClassItem *class = NULL;
2997 <
2998 <  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)
3015 <    class = map_to_conf(aconf->class_ptr);
3016 <
3017 <  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;
3028 <  }
3029 < }
3030 <
3031 < /* conf_add_server()
3032 < *
3033 < * inputs       - pointer to config item
3034 < *              - pointer to link count already on this conf
3035 < * output       - NONE
3036 < * side effects - Add a connect block
3037 < */
3038 < int
3039 < conf_add_server(struct ConfItem *conf, const char *class_name)
3040 < {
3041 <  struct AccessItem *aconf;
3042 <  struct split_nuh_item nuh;
3043 <  char conf_user[USERLEN + 1];
3044 <  char conf_host[HOSTLEN + 1];
3045 <
3046 <  aconf = map_to_conf(conf);
3047 <
3048 <  conf_add_class_to_conf(conf, class_name);
3049 <
3050 <  if (!aconf->host || !conf->name)
3051 <  {
3052 <    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
3053 <    ilog(L_WARN, "Bad connect block");
3054 <    return -1;
3055 <  }
3056 <
3057 <  if (EmptyString(aconf->passwd) && !IsConfCryptLink(aconf))
3058 <  {
3059 <    sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
3060 <                         conf->name);
3061 <    ilog(L_WARN, "Bad connect block, host %s", conf->name);
3062 <    return -1;
3063 <  }
3064 <
3065 <  nuh.nuhmask  = aconf->host;
3066 <  nuh.nickptr  = NULL;
3067 <  nuh.userptr  = conf_user;
3068 <  nuh.hostptr  = conf_host;
3069 <
3070 <  nuh.nicksize = 0;
3071 <  nuh.usersize = sizeof(conf_user);
3072 <  nuh.hostsize = sizeof(conf_host);
3073 <
3074 <  split_nuh(&nuh);
3075 <
3076 <  MyFree(aconf->host);
3077 <  aconf->host = NULL;
3078 <
3079 <  DupString(aconf->user, conf_user); /* somehow username checking for servers
3080 <                                 got lost in H6/7, will have to be re-added */
3081 <  DupString(aconf->host, conf_host);
3082 <
3083 <  lookup_confhost(conf);
3084 <
3085 <  return 0;
3086 < }
3087 <
3088 < /* conf_add_d_conf()
3089 < *
3090 < * inputs       - pointer to config item
3091 < * output       - NONE
3092 < * side effects - Add a d/D line
3093 < */
3094 < void
3095 < conf_add_d_conf(struct AccessItem *aconf)
3096 < {
3097 <  if (aconf->host == NULL)
3098 <    return;
3099 <
3100 <  aconf->user = NULL;
3101 <
3102 <  /* XXX - Should 'd' ever be in the old conf? For new conf we don't
3103 <   *       need this anyway, so I will disable it for now... -A1kmm
3104 <   */
3105 <  if (parse_netmask(aconf->host, NULL, NULL) == HM_HOST)
3106 <  {
3107 <    ilog(L_WARN, "Invalid Dline %s ignored", aconf->host);
3108 <    free_access_item(aconf);
3109 <  }
3110 <  else
3111 <  {
3112 <    /* XXX ensure user is NULL */
3113 <    MyFree(aconf->user);
3114 <    aconf->user = NULL;
3115 <    add_conf_by_address(CONF_DLINE, aconf);
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    }
1376   }
1377  
# Line 3127 | Line 1386 | yyerror(const char *msg)
1386   {
1387    char newlinebuf[IRCD_BUFSIZE];
1388  
1389 <  if (ypass != 1)
1389 >  if (conf_parser_ctx.pass != 1)
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(L_WARN, "\"%s\", line %u: %s: %s",
1396 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1397         conffilebuf, lineno + 1, msg, newlinebuf);
1398   }
1399  
1400 < int
1401 < conf_fbgets(char *lbuf, unsigned int max_size, FBFILE *fb)
1400 > void
1401 > conf_error_report(const char *msg)
1402   {
1403 <  if (fbgets(lbuf, max_size, fb) == NULL)
3144 <    return 0;
3145 <
3146 <  return strlen(lbuf);
3147 < }
1403 >  char newlinebuf[IRCD_BUFSIZE];
1404  
1405 < int
1406 < conf_yy_fatal_error(const char *msg)
1407 < {
1408 <  return 0;
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);
1411   }
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 3163 | Line 1421 | conf_yy_fatal_error(const char *msg)
1421   * Originally written by Dianora (Diane, db@db.net)
1422   */
1423   time_t
1424 < valid_tkline(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 <  while (*p)
1430 >  while ((tmpch = *p++))
1431    {
1432 <    if (IsDigit(*p))
3173 <    {
3174 <      result *= 10;
3175 <      result += ((*p) & 0xF);
3176 <      p++;
3177 <    }
3178 <    else
1432 >    if (!IsDigit(tmpch))
1433        return 0;
1434 +
1435 +    result *= 10;
1436 +    result += (tmpch & 0xF);
1437    }
1438  
1439 <  /* in the degenerate case where oper does a /quote kline 0 user@host :reason
1439 >  /*
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     */
3186
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 3213 | Line 1501 | valid_tkline(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;
3218 <  int nonwild = 0;
1504 >  unsigned char tmpch = '\0';
1505 >  unsigned int nonwild = 0;
1506    va_list args;
1507  
1508    /*
# Line 3234 | 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 3246 | 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 3268 | 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 3284 | Line 1576 | valid_wild_card(struct Client *source_p,
1576   *                if target_server is NULL and an "ON" is found error
1577   *                is reported.
1578   *                if reason pointer is NULL ignore pointer,
1579 < *                this allows usee of parse_a_line in unkline etc.
1579 > *                this allows use of parse_a_line in unkline etc.
1580   *
1581   * - Dianora
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 3313 | 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",
3317 <                 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),
3325 <               me.name, source_p->name, cmd);
1615 >    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1616      return -1;
1617    }
1618  
# Line 3336 | 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 3349 | 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);
3354 <        return -1;
1642 >        sendto_one_notice(source_p, &me, ":ON server not supported by %s", cmd);
1643 >        return -1;
1644        }
1645  
1646 <      if (!IsOperRemoteBan(source_p))
1646 >      if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
1647        {
1648 <        sendto_one(source_p, form_str(ERR_NOPRIVS),
3360 <                   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);
3368 <        return -1;
1654 >        sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1655 >        return -1;
1656        }
1657  
1658        *target_server = *parv;
# Line 3378 | 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 3386 | 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",
3390 <                 me.name, source_p->name);
1676 >      sendto_one_notice(source_p, &me, ":Invalid character '!' in kline");
1677        return -1;
1678      }
1679  
1680 <    if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 2, *up_p, *h_p))
1680 >    if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 2, *up_p, *h_p))
1681        return -1;
1682    }
1683    else
1684 <    if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 1, *up_p))
1684 >    if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 1, *up_p))
1685        return -1;
1686  
1687    if (reason != NULL)
1688    {
1689 <    if (parc != 0)
1689 >    if (parc != 0 && !EmptyString(*parv))
1690      {
1691        *reason = *parv;
1692 <      if (!valid_comment(source_p, *reason, YES))
1693 <        return -1;
1692 >      if (!valid_comment(source_p, *reason, 1))
1693 >        return -1;
1694      }
1695      else
1696        *reason = def_reason;
# Line 3443 | 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,
3475 <                   ":%s NOTICE %s :%s is E-lined",
3476 <                   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 3486 | 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' ||
3490 <        (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 3508 | Line 1792 | find_user_host(struct Client *source_p,
1792   int
1793   valid_comment(struct Client *source_p, char *comment, int warn)
1794   {
3511  if (strchr(comment, '"'))
3512  {
3513    if (warn)
3514      sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3515                 me.name, source_p->name);
3516    return 0;
3517  }
3518
1795    if (strlen(comment) > REASONLEN)
1796      comment[REASONLEN-1] = '\0';
1797  
# Line 3530 | 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 <  {
3542 <    /* use first two chars of the password they send in as salt */
3543 <    /* If the password in the conf is MD5, and ircd is linked
3544 <     * to scrypt on FreeBSD, or the standard crypt library on
3545 <     * glibc Linux, then this code will work fine on generating
3546 <     * the proper encrypted hash for comparison.
3547 <     */
3548 <    if (*aconf->passwd)
3549 <      encr = crypt(password, aconf->passwd);
3550 <    else
3551 <      encr = "";
3552 <  }
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 3561 | 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
1830 < *              - cluster type -- CLUSTER_KLINE etc. from s_conf.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
1833   * side effects - Take source_p send the pattern with args given
# Line 3573 | 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 3582 | 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 3634 | 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 3660 | 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 3676 | Line 1942 | split_nuh(struct split_nuh_item *const i
1942      }
1943    }
1944   }
3679
3680 /*
3681 * flags_to_ascii
3682 *
3683 * inputs       - flags is a bitmask
3684 *              - pointer to table of ascii letters corresponding
3685 *                to each bit
3686 *              - flag 1 for convert ToLower if bit missing
3687 *                0 if ignore.
3688 * output       - none
3689 * side effects - string pointed to by p has bitmap chars written to it
3690 */
3691 static void
3692 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3693               int lowerit)
3694 {
3695  unsigned int mask = 1;
3696  int i = 0;
3697
3698  for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3699  {
3700    if (flags & mask)
3701      *p++ = bit_table[i];
3702    else if (lowerit)
3703      *p++ = ToLower(bit_table[i]);
3704  }
3705  *p = '\0';
3706 }
3707
3708 /*
3709 * cidr_limit_reached
3710 *
3711 * inputs       - int flag allowing over_rule of limits
3712 *              - pointer to the ip to be added
3713 *              - pointer to the class
3714 * output       - non zero if limit reached
3715 *                0 if limit not reached
3716 * side effects -
3717 */
3718 static int
3719 cidr_limit_reached(int over_rule,
3720                   struct irc_ssaddr *ip, struct ClassItem *aclass)
3721 {
3722  dlink_node *ptr = NULL;
3723  struct CidrItem *cidr;
3724
3725  if (NumberPerCidr(aclass) <= 0)
3726    return 0;
3727
3728  if (ip->ss.ss_family == AF_INET)
3729  {
3730    if (CidrBitlenIPV4(aclass) <= 0)
3731      return 0;
3732
3733    DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3734    {
3735      cidr = ptr->data;
3736      if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3737      {
3738        if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3739          return -1;
3740        cidr->number_on_this_cidr++;
3741        return 0;
3742      }
3743    }
3744    cidr = MyMalloc(sizeof(struct CidrItem));
3745    cidr->number_on_this_cidr = 1;
3746    cidr->mask = *ip;
3747    mask_addr(&cidr->mask, CidrBitlenIPV4(aclass));
3748    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3749  }
3750 #ifdef IPV6
3751  else if (CidrBitlenIPV6(aclass) > 0)
3752  {
3753    DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3754    {
3755      cidr = ptr->data;
3756      if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3757      {
3758        if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3759          return -1;
3760        cidr->number_on_this_cidr++;
3761        return 0;
3762      }
3763    }
3764    cidr = MyMalloc(sizeof(struct CidrItem));
3765    cidr->number_on_this_cidr = 1;
3766    cidr->mask = *ip;
3767    mask_addr(&cidr->mask, CidrBitlenIPV6(aclass));
3768    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3769  }
3770 #endif
3771  return 0;
3772 }
3773
3774 /*
3775 * remove_from_cidr_check
3776 *
3777 * inputs       - pointer to the ip to be removed
3778 *              - pointer to the class
3779 * output       - NONE
3780 * side effects -
3781 */
3782 static void
3783 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3784 {
3785  dlink_node *ptr = NULL;
3786  dlink_node *next_ptr = NULL;
3787  struct CidrItem *cidr;
3788
3789  if (NumberPerCidr(aclass) == 0)
3790    return;
3791
3792  if (ip->ss.ss_family == AF_INET)
3793  {
3794    if (CidrBitlenIPV4(aclass) <= 0)
3795      return;
3796
3797    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3798    {
3799      cidr = ptr->data;
3800      if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3801      {
3802        cidr->number_on_this_cidr--;
3803        if (cidr->number_on_this_cidr == 0)
3804        {
3805          dlinkDelete(ptr, &aclass->list_ipv4);
3806          MyFree(cidr);
3807          return;
3808        }
3809      }
3810    }
3811  }
3812 #ifdef IPV6
3813  else if (CidrBitlenIPV6(aclass) > 0)
3814  {
3815    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3816    {
3817      cidr = ptr->data;
3818      if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3819      {
3820        cidr->number_on_this_cidr--;
3821        if (cidr->number_on_this_cidr == 0)
3822        {
3823          dlinkDelete(ptr, &aclass->list_ipv6);
3824          MyFree(cidr);
3825          return;
3826        }
3827      }
3828    }
3829  }
3830 #endif
3831 }
3832
3833 static void
3834 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3835                  dlink_list *old_list, dlink_list *new_list, int changed)
3836 {
3837  dlink_node *ptr;
3838  struct Client *client_p;
3839  struct ConfItem *conf;
3840  struct AccessItem *aconf;
3841
3842  if (!changed)
3843  {
3844    *new_list = *old_list;
3845    old_list->head = old_list->tail = NULL;
3846    old_list->length = 0;
3847    return;
3848  }
3849
3850  DLINK_FOREACH(ptr, local_client_list.head)
3851  {
3852    client_p = ptr->data;
3853    if (client_p->localClient->aftype != aftype)
3854      continue;
3855    if (dlink_list_length(&client_p->localClient->confs) == 0)
3856      continue;
3857
3858    conf = client_p->localClient->confs.tail->data;
3859    if (conf->type == CLIENT_TYPE)
3860    {
3861      aconf = map_to_conf(conf);
3862      if (aconf->class_ptr == oldcl)
3863        cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3864    }
3865  }
3866 }
3867
3868 /*
3869 * rebuild_cidr_class
3870 *
3871 * inputs       - pointer to old conf
3872 *              - pointer to new_class
3873 * output       - none
3874 * side effects - rebuilds the class link list of cidr blocks
3875 */
3876 void
3877 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3878 {
3879  struct ClassItem *old_class = map_to_conf(conf);
3880
3881  if (NumberPerCidr(old_class) > 0 && NumberPerCidr(new_class) > 0)
3882  {
3883    if (CidrBitlenIPV4(old_class) > 0 && CidrBitlenIPV4(new_class) > 0)
3884      rebuild_cidr_list(AF_INET, conf, new_class,
3885                        &old_class->list_ipv4, &new_class->list_ipv4,
3886                        CidrBitlenIPV4(old_class) != CidrBitlenIPV4(new_class));
3887
3888 #ifdef IPV6
3889    if (CidrBitlenIPV6(old_class) > 0 && CidrBitlenIPV6(new_class) > 0)
3890      rebuild_cidr_list(AF_INET6, conf, new_class,
3891                        &old_class->list_ipv6, &new_class->list_ipv6,
3892                        CidrBitlenIPV6(old_class) != CidrBitlenIPV6(new_class));
3893 #endif
3894  }
3895
3896  destroy_cidr_class(old_class);
3897 }
3898
3899 /*
3900 * destroy_cidr_list
3901 *
3902 * inputs       - pointer to class dlink list of cidr blocks
3903 * output       - none
3904 * side effects - completely destroys the class link list of cidr blocks
3905 */
3906 static void
3907 destroy_cidr_list(dlink_list *list)
3908 {
3909  dlink_node *ptr = NULL, *next_ptr = NULL;
3910
3911  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3912  {
3913    dlinkDelete(ptr, list);
3914    MyFree(ptr->data);
3915  }
3916 }
3917
3918 /*
3919 * destroy_cidr_class
3920 *
3921 * inputs       - pointer to class
3922 * output       - none
3923 * side effects - completely destroys the class link list of cidr blocks
3924 */
3925 static void
3926 destroy_cidr_class(struct ClassItem *aclass)
3927 {
3928  destroy_cidr_list(&aclass->list_ipv4);
3929  destroy_cidr_list(&aclass->list_ipv6);
3930 }

Diff Legend

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