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/trunk/src/conf.c (file contents):
Revision 1618 by michael, Tue Oct 30 21:04:38 2012 UTC vs.
Revision 4325 by michael, Fri Aug 1 18:06:07 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  conf.c: Configuration file functions.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 18 | Line 17
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file conf.c
23 > * \brief Configuration file functions.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28   #include "list.h"
29   #include "ircd_defs.h"
28 #include "balloc.h"
30   #include "conf.h"
31 < #include "s_serv.h"
31 > #include "server.h"
32   #include "resv.h"
33   #include "channel.h"
34   #include "client.h"
35   #include "event.h"
35 #include "hook.h"
36   #include "irc_string.h"
37   #include "s_bsd.h"
38   #include "ircd.h"
# Line 43 | Line 43
43   #include "fdlist.h"
44   #include "log.h"
45   #include "send.h"
46 #include "s_gline.h"
46   #include "memory.h"
47 < #include "irc_res.h"
47 > #include "res.h"
48   #include "userhost.h"
49 < #include "s_user.h"
49 > #include "user.h"
50   #include "channel_mode.h"
51   #include "parse.h"
52 < #include "s_misc.h"
52 > #include "misc.h"
53 > #include "conf_db.h"
54 > #include "conf_class.h"
55 > #include "motd.h"
56 > #include "ipcache.h"
57  
55 struct Callback *client_check_cb = NULL;
56 struct config_server_hide ConfigServerHide;
58  
59   /* general conf items link list root, other than k lines etc. */
60   dlink_list service_items = { NULL, NULL, 0 };
# Line 62 | Line 63 | dlink_list cluster_items = { NULL, NULL,
63   dlink_list oconf_items   = { NULL, NULL, 0 };
64   dlink_list uconf_items   = { NULL, NULL, 0 };
65   dlink_list xconf_items   = { NULL, NULL, 0 };
65 dlink_list rxconf_items  = { NULL, NULL, 0 };
66 dlink_list rkconf_items  = { NULL, NULL, 0 };
66   dlink_list nresv_items   = { NULL, NULL, 0 };
67 < dlink_list class_items   = { NULL, NULL, 0 };
69 <
70 < dlink_list temporary_xlines  = { NULL, NULL, 0 };
71 < dlink_list temporary_resv = { NULL, NULL, 0 };
67 > dlink_list cresv_items   = { NULL, NULL, 0 };
68  
69   extern unsigned int lineno;
70   extern char linebuf[];
71   extern char conffilebuf[IRCD_BUFSIZE];
72   extern int yyparse(); /* defined in y.tab.c */
73  
78 struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
79
74   /* internally defined functions */
75   static void read_conf(FILE *);
76   static void clear_out_old_conf(void);
83 static void flush_deleted_I_P(void);
77   static void expire_tklines(dlink_list *);
78 < static void garbage_collect_ip_entries(void);
79 < static int hash_ip(struct irc_ssaddr *);
80 < static int verify_access(struct Client *, const char *);
88 < static int attach_iline(struct Client *, struct ConfItem *);
89 < static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
90 < static void parse_conf_file(int, int);
91 < static dlink_list *map_to_list(ConfType);
92 < static struct AccessItem *find_regexp_kline(const char *[]);
78 > static int verify_access(struct Client *);
79 > static int attach_iline(struct Client *, struct MaskItem *);
80 > static dlink_list *map_to_list(enum maskitem_type);
81   static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
82  
95 /*
96 * bit_len
97 */
98 static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
99 static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
100 static void destroy_cidr_class(struct ClassItem *);
101
102 static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
103
104 /* address of default class conf */
105 static struct ConfItem *class_default;
106
107 /* usually, with hash tables, you use a prime number...
108 * but in this case I am dealing with ip addresses,
109 * not ascii strings.
110 */
111 #define IP_HASH_SIZE 0x1000
112
113 struct ip_entry
114 {
115  struct irc_ssaddr ip;
116  int count;
117  time_t last_attempt;
118  struct ip_entry *next;
119 };
120
121 static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
122 static BlockHeap *ip_entry_heap = NULL;
123 static int ip_entries_count = 0;
124
125
126 void *
127 map_to_conf(struct ConfItem *aconf)
128 {
129  void *conf;
130  conf = (void *)((uintptr_t)aconf +
131                  (uintptr_t)sizeof(struct ConfItem));
132  return(conf);
133 }
134
135 struct ConfItem *
136 unmap_conf_item(void *aconf)
137 {
138  struct ConfItem *conf;
139
140  conf = (struct ConfItem *)((uintptr_t)aconf -
141                             (uintptr_t)sizeof(struct ConfItem));
142  return(conf);
143 }
83  
84   /* conf_dns_callback()
85   *
86 < * inputs       - pointer to struct AccessItem
86 > * inputs       - pointer to struct MaskItem
87   *              - pointer to DNSReply reply
88   * output       - none
89   * side effects - called when resolver query finishes
# Line 155 | Line 94 | unmap_conf_item(void *aconf)
94   static void
95   conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
96   {
97 <  struct AccessItem *aconf = vptr;
97 >  struct MaskItem *conf = vptr;
98  
99 <  aconf->dns_pending = 0;
99 >  conf->dns_pending = 0;
100  
101 <  if (addr != NULL)
102 <    memcpy(&aconf->addr, addr, sizeof(aconf->addr));
101 >  if (addr)
102 >    memcpy(&conf->addr, addr, sizeof(conf->addr));
103    else
104 <    aconf->dns_failed = 1;
104 >    conf->dns_failed = 1;
105   }
106  
107   /* conf_dns_lookup()
# Line 172 | Line 111 | conf_dns_callback(void *vptr, const stru
111   * allocate a dns_query and start ns lookup.
112   */
113   static void
114 < conf_dns_lookup(struct AccessItem *aconf)
114 > conf_dns_lookup(struct MaskItem *conf)
115   {
116 <  if (!aconf->dns_pending)
116 >  if (!conf->dns_pending)
117    {
118 <    aconf->dns_pending = 1;
119 <    gethost_byname(conf_dns_callback, aconf, aconf->host);
118 >    conf->dns_pending = 1;
119 >    gethost_byname(conf_dns_callback, conf, conf->host);
120    }
121   }
122  
123 < /* make_conf_item()
124 < *
186 < * inputs       - type of item
187 < * output       - pointer to new conf entry
188 < * side effects - none
189 < */
190 < struct ConfItem *
191 < make_conf_item(ConfType type)
123 > struct MaskItem *
124 > conf_make(enum maskitem_type type)
125   {
126 <  struct ConfItem *conf = NULL;
127 <  struct AccessItem *aconf = NULL;
195 <  struct ClassItem *aclass = NULL;
196 <  int status = 0;
197 <
198 <  switch (type)
199 <  {
200 <  case DLINE_TYPE:
201 <  case EXEMPTDLINE_TYPE:
202 <  case GLINE_TYPE:
203 <  case KLINE_TYPE:
204 <  case CLIENT_TYPE:
205 <  case OPER_TYPE:
206 <  case SERVER_TYPE:
207 <    conf = MyMalloc(sizeof(struct ConfItem) +
208 <                    sizeof(struct AccessItem));
209 <    aconf = map_to_conf(conf);
210 <    aconf->aftype = AF_INET;
211 <
212 <    /* Yes, sigh. switch on type again */
213 <    switch (type)
214 <    {
215 <    case EXEMPTDLINE_TYPE:
216 <      status = CONF_EXEMPTDLINE;
217 <      break;
218 <
219 <    case DLINE_TYPE:
220 <      status = CONF_DLINE;
221 <      break;
126 >  struct MaskItem *conf = MyCalloc(sizeof(*conf));
127 >  dlink_list *list = NULL;
128  
129 <    case KLINE_TYPE:
130 <      status = CONF_KLINE;
131 <      break;
226 <
227 <    case GLINE_TYPE:
228 <      status = CONF_GLINE;
229 <      break;
230 <
231 <    case CLIENT_TYPE:
232 <      status = CONF_CLIENT;
233 <      break;
234 <
235 <    case OPER_TYPE:
236 <      status = CONF_OPERATOR;
237 <      dlinkAdd(conf, &conf->node, &oconf_items);
238 <      break;
239 <
240 <    case SERVER_TYPE:
241 <      status = CONF_SERVER;
242 <      dlinkAdd(conf, &conf->node, &server_items);
243 <      break;
244 <
245 <    default:
246 <      break;
247 <    }
248 <    aconf->status = status;
249 <    break;
250 <
251 <  case ULINE_TYPE:
252 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
253 <                                       sizeof(struct MatchItem));
254 <    dlinkAdd(conf, &conf->node, &uconf_items);
255 <    break;
256 <
257 <  case XLINE_TYPE:
258 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
259 <                                       sizeof(struct MatchItem));
260 <    dlinkAdd(conf, &conf->node, &xconf_items);
261 <    break;
262 < #ifdef HAVE_LIBPCRE
263 <  case RXLINE_TYPE:
264 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
265 <                                       sizeof(struct MatchItem));
266 <    dlinkAdd(conf, &conf->node, &rxconf_items);
267 <    break;
268 <
269 <  case RKLINE_TYPE:
270 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
271 <                                       sizeof(struct AccessItem));
272 <    aconf = map_to_conf(conf);
273 <    aconf->status = CONF_KLINE;
274 <    dlinkAdd(conf, &conf->node, &rkconf_items);
275 <    break;
276 < #endif
277 <  case CLUSTER_TYPE:
278 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
279 <    dlinkAdd(conf, &conf->node, &cluster_items);
280 <    break;
281 <
282 <  case CRESV_TYPE:
283 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
284 <                                       sizeof(struct ResvChannel));
285 <    break;
286 <
287 <  case NRESV_TYPE:
288 <    conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
289 <                                       sizeof(struct MatchItem));
290 <    dlinkAdd(conf, &conf->node, &nresv_items);
291 <    break;
292 <
293 <  case SERVICE_TYPE:
294 <    status = CONF_SERVICE;
295 <    conf = MyMalloc(sizeof(struct ConfItem));
296 <    dlinkAdd(conf, &conf->node, &service_items);
297 <    break;
298 <
299 <  case CLASS_TYPE:
300 <    conf = MyMalloc(sizeof(struct ConfItem) +
301 <                           sizeof(struct ClassItem));
302 <    dlinkAdd(conf, &conf->node, &class_items);
303 <
304 <    aclass = map_to_conf(conf);
305 <    aclass->active = 1;
306 <    aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
307 <    aclass->ping_freq = DEFAULT_PINGFREQUENCY;
308 <    aclass->max_total = MAXIMUM_LINKS_DEFAULT;
309 <    aclass->max_sendq = DEFAULT_SENDQ;
310 <    aclass->max_recvq = DEFAULT_RECVQ;
311 <
312 <    break;
313 <
314 <  default:
315 <    conf = NULL;
316 <    break;
317 <  }
318 <
319 <  /* XXX Yes, this will core if default is hit. I want it to for now - db */
320 <  conf->type = type;
129 >  conf->type   = type;
130 >  conf->active = 1;
131 >  conf->aftype = AF_INET;
132  
133 +  if ((list = map_to_list(type)))
134 +    dlinkAdd(conf, &conf->node, list);
135    return conf;
136   }
137  
138   void
139 < delete_conf_item(struct ConfItem *conf)
139 > conf_free(struct MaskItem *conf)
140   {
141 <  dlink_node *m = NULL, *m_next = NULL;
142 <  struct MatchItem *match_item;
143 <  struct AccessItem *aconf;
144 <  ConfType type = conf->type;
141 >  dlink_node *ptr = NULL, *ptr_next = NULL;
142 >  dlink_list *list = NULL;
143 >
144 >  if (conf->node.next)
145 >    if ((list = map_to_list(conf->type)))
146 >      dlinkDelete(&conf->node, list);
147  
148    MyFree(conf->name);
334  conf->name = NULL;
149  
150 <  switch(type)
151 <  {
152 <  case DLINE_TYPE:
153 <  case EXEMPTDLINE_TYPE:
154 <  case GLINE_TYPE:
155 <  case KLINE_TYPE:
156 <  case CLIENT_TYPE:
157 <  case OPER_TYPE:
158 <  case SERVER_TYPE:
159 <    aconf = map_to_conf(conf);
160 <
161 <    if (aconf->dns_pending)
162 <      delete_resolver_queries(aconf);
163 <    if (aconf->passwd != NULL)
164 <      memset(aconf->passwd, 0, strlen(aconf->passwd));
351 <    if (aconf->spasswd != NULL)
352 <      memset(aconf->spasswd, 0, strlen(aconf->spasswd));
353 <    aconf->class_ptr = NULL;
354 <
355 <    MyFree(aconf->passwd);
356 <    MyFree(aconf->spasswd);
357 <    MyFree(aconf->reason);
358 <    MyFree(aconf->oper_reason);
359 <    MyFree(aconf->user);
360 <    MyFree(aconf->host);
150 >  if (conf->dns_pending)
151 >    delete_resolver_queries(conf);
152 >  if (conf->passwd)
153 >    memset(conf->passwd, 0, strlen(conf->passwd));
154 >  if (conf->spasswd)
155 >    memset(conf->spasswd, 0, strlen(conf->spasswd));
156 >
157 >  conf->class = NULL;
158 >
159 >  MyFree(conf->passwd);
160 >  MyFree(conf->spasswd);
161 >  MyFree(conf->reason);
162 >  MyFree(conf->certfp);
163 >  MyFree(conf->user);
164 >  MyFree(conf->host);
165   #ifdef HAVE_LIBCRYPTO
166 <    MyFree(aconf->cipher_list);
166 >  MyFree(conf->cipher_list);
167  
168 <    if (aconf->rsa_public_key)
169 <      RSA_free(aconf->rsa_public_key);
366 <    MyFree(aconf->rsa_public_key_file);
168 >  if (conf->rsa_public_key)
169 >    RSA_free(conf->rsa_public_key);
170   #endif
171 <
172 <    /* Yes, sigh. switch on type again */
173 <    switch(type)
174 <    {
175 <    case EXEMPTDLINE_TYPE:
373 <    case DLINE_TYPE:
374 <    case GLINE_TYPE:
375 <    case KLINE_TYPE:
376 <    case CLIENT_TYPE:
377 <      MyFree(conf);
378 <      break;
379 <
380 <    case OPER_TYPE:
381 <      aconf = map_to_conf(conf);
382 <      if (!IsConfIllegal(aconf))
383 <        dlinkDelete(&conf->node, &oconf_items);
384 <      MyFree(conf);
385 <      break;
386 <
387 <    case SERVER_TYPE:
388 <      aconf = map_to_conf(conf);
389 <
390 <      DLINK_FOREACH_SAFE(m, m_next, aconf->hub_list.head)
391 <      {
392 <        MyFree(m->data);
393 <        free_dlink_node(m);
394 <      }
395 <
396 <      DLINK_FOREACH_SAFE(m, m_next, aconf->leaf_list.head)
397 <      {
398 <        MyFree(m->data);
399 <        free_dlink_node(m);  
400 <      }
401 <
402 <      if (!IsConfIllegal(aconf))
403 <        dlinkDelete(&conf->node, &server_items);
404 <      MyFree(conf);
405 <      break;
406 <
407 <    default:
408 <      break;
409 <    }
410 <    break;
411 <
412 <  case ULINE_TYPE:
413 <    match_item = map_to_conf(conf);
414 <    MyFree(match_item->user);
415 <    MyFree(match_item->host);
416 <    MyFree(match_item->reason);
417 <    MyFree(match_item->oper_reason);
418 <    dlinkDelete(&conf->node, &uconf_items);
419 <    MyFree(conf);
420 <    break;
421 <
422 <  case XLINE_TYPE:
423 <    match_item = map_to_conf(conf);
424 <    MyFree(match_item->user);
425 <    MyFree(match_item->host);
426 <    MyFree(match_item->reason);
427 <    MyFree(match_item->oper_reason);
428 <    dlinkDelete(&conf->node, &xconf_items);
429 <    MyFree(conf);
430 <    break;
431 < #ifdef HAVE_LIBPCRE
432 <  case RKLINE_TYPE:
433 <    aconf = map_to_conf(conf);
434 <    MyFree(aconf->regexuser);
435 <    MyFree(aconf->regexhost);
436 <    MyFree(aconf->user);
437 <    MyFree(aconf->host);
438 <    MyFree(aconf->reason);
439 <    MyFree(aconf->oper_reason);
440 <    dlinkDelete(&conf->node, &rkconf_items);
441 <    MyFree(conf);
442 <    break;
443 <
444 <  case RXLINE_TYPE:
445 <    MyFree(conf->regexpname);
446 <    match_item = map_to_conf(conf);
447 <    MyFree(match_item->user);
448 <    MyFree(match_item->host);
449 <    MyFree(match_item->reason);
450 <    MyFree(match_item->oper_reason);
451 <    dlinkDelete(&conf->node, &rxconf_items);
452 <    MyFree(conf);
453 <    break;
454 < #endif
455 <  case NRESV_TYPE:
456 <    match_item = map_to_conf(conf);
457 <    MyFree(match_item->user);
458 <    MyFree(match_item->host);
459 <    MyFree(match_item->reason);
460 <    MyFree(match_item->oper_reason);
461 <    dlinkDelete(&conf->node, &nresv_items);
462 <
463 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
464 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
465 <        free_dlink_node(m);
466 <
467 <    MyFree(conf);
468 <    break;
469 <
470 <  case CLUSTER_TYPE:
471 <    dlinkDelete(&conf->node, &cluster_items);
472 <    MyFree(conf);
473 <    break;
474 <
475 <  case CRESV_TYPE:
476 <    if (conf->flags & CONF_FLAGS_TEMPORARY)
477 <      if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
478 <        free_dlink_node(m);
479 <
480 <    MyFree(conf);
481 <    break;
482 <
483 <  case CLASS_TYPE:
484 <    dlinkDelete(&conf->node, &class_items);
485 <    MyFree(conf);
486 <    break;
487 <
488 <  case SERVICE_TYPE:
489 <    dlinkDelete(&conf->node, &service_items);
490 <    MyFree(conf);
491 <    break;
492 <
493 <  default:
494 <    break;
171 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->hub_list.head)
172 >  {
173 >    MyFree(ptr->data);
174 >    dlinkDelete(ptr, &conf->hub_list);
175 >    free_dlink_node(ptr);
176    }
496 }
177  
178 < /* free_access_item()
499 < *
500 < * inputs       - pointer to conf to free
501 < * output       - none
502 < * side effects - crucial password fields are zeroed, conf is freed
503 < */
504 < void
505 < free_access_item(struct AccessItem *aconf)
506 < {
507 <  struct ConfItem *conf;
508 <
509 <  if (aconf == NULL)
510 <    return;
511 <  conf = unmap_conf_item(aconf);
512 <  delete_conf_item(conf);
513 < }
514 <
515 < static const unsigned int shared_bit_table[] =
516 <  { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
517 <
518 < /* report_confitem_types()
519 < *
520 < * inputs       - pointer to client requesting confitem report
521 < *              - ConfType to report
522 < * output       - none
523 < * side effects -
524 < */
525 < void
526 < report_confitem_types(struct Client *source_p, ConfType type)
527 < {
528 <  dlink_node *ptr = NULL, *dptr = NULL;
529 <  struct ConfItem *conf = NULL;
530 <  struct AccessItem *aconf = NULL;
531 <  struct MatchItem *matchitem = NULL;
532 <  struct ClassItem *classitem = NULL;
533 <  char buf[12];
534 <  char *p = NULL;
535 <
536 <  switch (type)
178 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->leaf_list.head)
179    {
180 <  case XLINE_TYPE:
181 <    DLINK_FOREACH(ptr, xconf_items.head)
182 <    {
183 <      conf = ptr->data;
542 <      matchitem = map_to_conf(conf);
543 <
544 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
545 <                 me.name, source_p->name,
546 <                 matchitem->hold ? "x": "X", matchitem->count,
547 <                 conf->name, matchitem->reason);
548 <    }
549 <    break;
550 <
551 < #ifdef HAVE_LIBPCRE
552 <  case RXLINE_TYPE:
553 <    DLINK_FOREACH(ptr, rxconf_items.head)
554 <    {
555 <      conf = ptr->data;
556 <      matchitem = map_to_conf(conf);
557 <
558 <      sendto_one(source_p, form_str(RPL_STATSXLINE),
559 <                 me.name, source_p->name,
560 <                 "XR", matchitem->count,
561 <                 conf->name, matchitem->reason);
562 <    }
563 <    break;
564 <
565 <  case RKLINE_TYPE:
566 <    DLINK_FOREACH(ptr, rkconf_items.head)
567 <    {
568 <      aconf = map_to_conf((conf = ptr->data));
569 <
570 <      sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
571 <                 source_p->name, "KR", aconf->host, aconf->user,
572 <                 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
573 <    }
574 <    break;
575 < #endif
576 <
577 <  case ULINE_TYPE:
578 <    DLINK_FOREACH(ptr, uconf_items.head)
579 <    {
580 <      conf = ptr->data;
581 <      matchitem = map_to_conf(conf);
582 <
583 <      p = buf;
584 <
585 <      /* some of these are redundant for the sake of
586 <       * consistency with cluster{} flags
587 <       */
588 <      *p++ = 'c';
589 <      flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
590 <
591 <      sendto_one(source_p, form_str(RPL_STATSULINE),
592 <                 me.name, source_p->name, conf->name,
593 <                 matchitem->user?matchitem->user: "*",
594 <                 matchitem->host?matchitem->host: "*", buf);
595 <    }
596 <
597 <    DLINK_FOREACH(ptr, cluster_items.head)
598 <    {
599 <      conf = ptr->data;
600 <
601 <      p = buf;
602 <
603 <      *p++ = 'C';
604 <      flags_to_ascii(conf->flags, shared_bit_table, p, 0);
605 <
606 <      sendto_one(source_p, form_str(RPL_STATSULINE),
607 <                 me.name, source_p->name, conf->name,
608 <                 "*", "*", buf);
609 <    }
610 <
611 <    break;
612 <
613 <  case OPER_TYPE:
614 <    DLINK_FOREACH(ptr, oconf_items.head)
615 <    {
616 <      conf = ptr->data;
617 <      aconf = map_to_conf(conf);
618 <
619 <      /* Don't allow non opers to see oper privs */
620 <      if (HasUMode(source_p, UMODE_OPER))
621 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
622 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
623 <                   conf->name, oper_privs_as_string(aconf->port),
624 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
625 <      else
626 <        sendto_one(source_p, form_str(RPL_STATSOLINE),
627 <                   me.name, source_p->name, 'O', aconf->user, aconf->host,
628 <                   conf->name, "0",
629 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
630 <    }
631 <    break;
632 <
633 <  case CLASS_TYPE:
634 <    DLINK_FOREACH(ptr, class_items.head)
635 <    {
636 <      conf = ptr->data;
637 <      classitem = map_to_conf(conf);
638 <      sendto_one(source_p, form_str(RPL_STATSYLINE),
639 <                 me.name, source_p->name, 'Y',
640 <                 conf->name, classitem->ping_freq,
641 <                 classitem->con_freq,
642 <                 classitem->max_total, classitem->max_sendq,
643 <                 classitem->max_recvq,
644 <                 classitem->curr_user_count,
645 <                 classitem->number_per_cidr, classitem->cidr_bitlen_ipv4,
646 <                 classitem->number_per_cidr, classitem->cidr_bitlen_ipv6,
647 <                 classitem->active ? "active" : "disabled");
648 <    }
649 <    break;
650 <
651 <  case CONF_TYPE:
652 <  case CLIENT_TYPE:
653 <    break;
654 <
655 <  case SERVICE_TYPE:
656 <    DLINK_FOREACH(ptr, service_items.head)
657 <    {
658 <      conf = ptr->data;
659 <      sendto_one(source_p, form_str(RPL_STATSSERVICE),
660 <                 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
661 <    }
662 <    break;
663 <
664 <  case SERVER_TYPE:
665 <    DLINK_FOREACH(ptr, server_items.head)
666 <    {
667 <      p = buf;
668 <
669 <      conf = ptr->data;
670 <      aconf = map_to_conf(conf);
671 <
672 <      buf[0] = '\0';
673 <
674 <      if (IsConfAllowAutoConn(aconf))
675 <        *p++ = 'A';
676 <      if (IsConfSSL(aconf))
677 <        *p++ = 'S';
678 <      if (buf[0] == '\0')
679 <        *p++ = '*';
680 <
681 <      *p = '\0';
682 <
683 <      /*
684 <       * Allow admins to see actual ips unless hide_server_ips is enabled
685 <       */
686 <      if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
687 <        sendto_one(source_p, form_str(RPL_STATSCLINE),
688 <                   me.name, source_p->name, 'C', aconf->host,
689 <                   buf, conf->name, aconf->port,
690 <                   aconf->class_ptr ? aconf->class_ptr->name : "<default>");
691 <        else
692 <          sendto_one(source_p, form_str(RPL_STATSCLINE),
693 <                     me.name, source_p->name, 'C',
694 <                     "*@127.0.0.1", buf, conf->name, aconf->port,
695 <                     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
696 <    }
697 <    break;
698 <
699 <  case HUB_TYPE:
700 <    DLINK_FOREACH(ptr, server_items.head)
701 <    {
702 <      conf = ptr->data;
703 <      aconf = map_to_conf(conf);
704 <
705 <      DLINK_FOREACH(dptr, aconf->hub_list.head)
706 <        sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
707 <                   source_p->name, 'H', dptr->data, conf->name, 0, "*");
708 <    }
709 <    break;
710 <
711 <  case LEAF_TYPE:
712 <    DLINK_FOREACH(ptr, server_items.head)
713 <    {
714 <      conf = ptr->data;
715 <      aconf = map_to_conf(conf);
180 >    MyFree(ptr->data);
181 >    dlinkDelete(ptr, &conf->leaf_list);
182 >    free_dlink_node(ptr);
183 >  }
184  
185 <      DLINK_FOREACH(dptr, aconf->leaf_list.head)
186 <        sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
187 <                   source_p->name, 'L', dptr->data, conf->name, 0, "*");
720 <    }
721 <    break;
185 >  DLINK_FOREACH_SAFE(ptr, ptr_next, conf->exempt_list.head)
186 >  {
187 >    struct exempt *exptr = ptr->data;
188  
189 <  case GLINE_TYPE:
190 <  case KLINE_TYPE:
191 <  case DLINE_TYPE:
192 <  case EXEMPTDLINE_TYPE:
193 <  case CRESV_TYPE:
728 <  case NRESV_TYPE:
729 <  case CLUSTER_TYPE:
730 <  default:
731 <    break;
189 >    dlinkDelete(ptr, &conf->exempt_list);
190 >    MyFree(exptr->name);
191 >    MyFree(exptr->user);
192 >    MyFree(exptr->host);
193 >    MyFree(exptr);
194    }
195 +
196 +  MyFree(conf);
197   }
198  
199   /* check_client()
# Line 745 | Line 209 | report_confitem_types(struct Client *sou
209   *                Look for conf lines which have the same
210   *                status as the flags passed.
211   */
212 < static void *
213 < check_client(va_list args)
212 > int
213 > check_client(struct Client *source_p)
214   {
751  struct Client *source_p = va_arg(args, struct Client *);
752  const char *username = va_arg(args, const char *);
215    int i;
216 <
217 <  /* I'm already in big trouble if source_p->localClient is NULL -db */
218 <  if ((i = verify_access(source_p, username)))
757 <    ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
216 >
217 >  if ((i = verify_access(source_p)))
218 >    ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
219           source_p->name, source_p->sockhost);
220  
221    switch (i)
# Line 762 | Line 223 | check_client(va_list args)
223      case TOO_MANY:
224        sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
225                             "Too many on IP for %s (%s).",
226 <                           get_client_name(source_p, SHOW_IP),
227 <                           source_p->sockhost);
226 >                           get_client_name(source_p, SHOW_IP),
227 >                           source_p->sockhost);
228        ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
229 <           get_client_name(source_p, SHOW_IP));
229 >           get_client_name(source_p, SHOW_IP));
230        ++ServerStats.is_ref;
231 <      exit_client(source_p, &me, "No more connections allowed on that IP");
231 >      exit_client(source_p, "No more connections allowed on that IP");
232        break;
233  
234      case I_LINE_FULL:
235        sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
236                             "auth{} block is full for %s (%s).",
237 <                           get_client_name(source_p, SHOW_IP),
238 <                           source_p->sockhost);
237 >                           get_client_name(source_p, SHOW_IP),
238 >                           source_p->sockhost);
239        ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
240 <           get_client_name(source_p, SHOW_IP));
240 >           get_client_name(source_p, SHOW_IP));
241        ++ServerStats.is_ref;
242 <      exit_client(source_p, &me,
782 <                "No more connections allowed in your connection class");
242 >      exit_client(source_p, "No more connections allowed in your connection class");
243        break;
244  
245      case NOT_AUTHORIZED:
# Line 787 | Line 247 | check_client(va_list args)
247        /* jdc - lists server name & port connections are on */
248        /*       a purely cosmetical change */
249        sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
250 <                           "Unauthorized client connection from %s [%s] on [%s/%u].",
251 <                           get_client_name(source_p, SHOW_IP),
252 <                           source_p->sockhost,
253 <                           source_p->localClient->listener->name,
254 <                           source_p->localClient->listener->port);
250 >                           "Unauthorized client connection from %s [%s] on [%s/%u].",
251 >                           get_client_name(source_p, SHOW_IP),
252 >                           source_p->sockhost,
253 >                           source_p->localClient->listener->name,
254 >                           source_p->localClient->listener->port);
255        ilog(LOG_TYPE_IRCD,
256 <          "Unauthorized client connection from %s on [%s/%u].",
257 <          get_client_name(source_p, SHOW_IP),
258 <          source_p->localClient->listener->name,
259 <          source_p->localClient->listener->port);
256 >           "Unauthorized client connection from %s on [%s/%u].",
257 >           get_client_name(source_p, SHOW_IP),
258 >           source_p->localClient->listener->name,
259 >           source_p->localClient->listener->port);
260  
261 <      exit_client(source_p, &me, "You are not authorized to use this server");
261 >      exit_client(source_p, "You are not authorized to use this server");
262        break;
263  
264     case BANNED_CLIENT:
265 <     exit_client(source_p, &me, "Banned");
265 >     exit_client(source_p, "Banned");
266       ++ServerStats.is_ref;
267       break;
268  
# Line 811 | Line 271 | check_client(va_list args)
271       break;
272    }
273  
274 <  return (i < 0 ? NULL : source_p);
274 >  return (i < 0 ? 0 : 1);
275   }
276  
277   /* verify_access()
278   *
279   * inputs       - pointer to client to verify
820 *              - pointer to proposed username
280   * output       - 0 if success -'ve if not
281   * side effect  - find the first (best) I line to attach.
282   */
283   static int
284 < verify_access(struct Client *client_p, const char *username)
284 > verify_access(struct Client *client_p)
285   {
286 <  struct AccessItem *aconf = NULL, *rkconf = NULL;
287 <  struct ConfItem *conf = NULL;
829 <  char non_ident[USERLEN + 1] = { '~', '\0' };
830 <  const char *uhi[3];
286 >  struct MaskItem *conf = NULL;
287 >  char non_ident[USERLEN + 1] = "~";
288  
289    if (IsGotId(client_p))
290    {
291 <    aconf = find_address_conf(client_p->host, client_p->username,
292 <                             &client_p->localClient->ip,
293 <                             client_p->localClient->aftype,
291 >    conf = find_address_conf(client_p->host, client_p->username,
292 >                             &client_p->localClient->ip,
293 >                             client_p->localClient->aftype,
294                               client_p->localClient->passwd);
295    }
296    else
297    {
298 <    strlcpy(non_ident+1, username, sizeof(non_ident)-1);
299 <    aconf = find_address_conf(client_p->host,non_ident,
300 <                             &client_p->localClient->ip,
301 <                             client_p->localClient->aftype,
302 <                             client_p->localClient->passwd);
298 >    strlcpy(non_ident + 1, client_p->username, sizeof(non_ident) - 1);
299 >    conf = find_address_conf(client_p->host,non_ident,
300 >                             &client_p->localClient->ip,
301 >                             client_p->localClient->aftype,
302 >                             client_p->localClient->passwd);
303    }
304  
305 <  uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
849 <  uhi[1] = client_p->host;
850 <  uhi[2] = client_p->sockhost;
851 <
852 <  rkconf = find_regexp_kline(uhi);
853 <
854 <  if (aconf != NULL)
305 >  if (conf)
306    {
307 <    if (IsConfClient(aconf) && !rkconf)
307 >    if (IsConfClient(conf))
308      {
309 <      conf = unmap_conf_item(aconf);
859 <
860 <      if (IsConfRedir(aconf))
309 >      if (IsConfRedir(conf))
310        {
311 <        sendto_one(client_p, form_str(RPL_REDIR),
312 <                   me.name, client_p->name,
313 <                   conf->name ? conf->name : "",
314 <                   aconf->port);
866 <        return(NOT_AUTHORIZED);
311 >        sendto_one_numeric(client_p, &me, RPL_REDIR,
312 >                           conf->name ? conf->name : "",
313 >                           conf->port);
314 >        return NOT_AUTHORIZED;
315        }
316  
317 <      if (IsConfDoIdentd(aconf))
318 <        SetNeedId(client_p);
317 >      if (IsConfDoIdentd(conf))
318 >        SetNeedId(client_p);
319  
320        /* Thanks for spoof idea amm */
321 <      if (IsConfDoSpoofIp(aconf))
321 >      if (IsConfDoSpoofIp(conf))
322        {
323 <        conf = unmap_conf_item(aconf);
876 <
877 <        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
323 >        if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(conf))
324            sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
325                                 "%s spoofing: %s as %s",
326                                 client_p->name, client_p->host, conf->name);
327          strlcpy(client_p->host, conf->name, sizeof(client_p->host));
328 <        SetIPSpoof(client_p);
328 >        AddFlag(client_p, FLAGS_IP_SPOOFING | FLAGS_AUTH_SPOOF);
329        }
330  
331 <      return(attach_iline(client_p, conf));
331 >      return attach_iline(client_p, conf);
332      }
333 <    else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
333 >    else if (IsConfKill(conf) || (ConfigFileEntry.glines && IsConfGline(conf)))
334      {
335 <      /* XXX */
336 <      aconf = rkconf ? rkconf : aconf;
337 <      if (IsConfGline(aconf))
338 <        sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
893 <                   client_p->name);
894 <      sendto_one(client_p, ":%s NOTICE %s :*** Banned: %s",
895 <                 me.name, client_p->name, aconf->reason);
896 <      return(BANNED_CLIENT);
335 >      if (IsConfGline(conf))
336 >        sendto_one_notice(client_p, &me, ":*** G-lined");
337 >      sendto_one_notice(client_p, &me, ":*** Banned: %s", conf->reason);
338 >      return BANNED_CLIENT;
339      }
340    }
341  
342 <  return(NOT_AUTHORIZED);
342 >  return NOT_AUTHORIZED;
343   }
344  
345   /* attach_iline()
# Line 908 | Line 350 | verify_access(struct Client *client_p, c
350   * side effects - do actual attach
351   */
352   static int
353 < attach_iline(struct Client *client_p, struct ConfItem *conf)
353 > attach_iline(struct Client *client_p, struct MaskItem *conf)
354   {
355 <  struct AccessItem *aconf;
914 <  struct ClassItem *aclass;
355 >  struct ClassItem *class = NULL;
356    struct ip_entry *ip_found;
357    int a_limit_reached = 0;
358 <  int local = 0, global = 0, ident = 0;
358 >  unsigned int local = 0, global = 0, ident = 0;
359  
360 <  ip_found = find_or_add_ip(&client_p->localClient->ip);
360 >  assert(conf->class);
361 >
362 >  ip_found = ipcache_find_or_add_address(&client_p->localClient->ip);
363    ip_found->count++;
364    SetIpHash(client_p);
365  
366 <  aconf = map_to_conf(conf);
924 <  if (aconf->class_ptr == NULL)
925 <    return NOT_AUTHORIZED;  /* If class is missing, this is best */
926 <
927 <  aclass = map_to_conf(aconf->class_ptr);
366 >  class = conf->class;
367  
368    count_user_host(client_p->username, client_p->host,
369                    &global, &local, &ident);
# Line 933 | Line 372 | attach_iline(struct Client *client_p, st
372     * setting a_limit_reached if any limit is reached.
373     * - Dianora
374     */
375 <  if (aclass->max_total != 0 && aclass->curr_user_count >= aclass->max_total)
375 >  if (class->max_total && class->ref_count >= class->max_total)
376      a_limit_reached = 1;
377 <  else if (aclass->max_perip != 0 && ip_found->count > aclass->max_perip)
377 >  else if (class->max_perip && ip_found->count > class->max_perip)
378      a_limit_reached = 1;
379 <  else if (aclass->max_local != 0 && local >= aclass->max_local)
379 >  else if (class->max_local && local >= class->max_local)
380      a_limit_reached = 1;
381 <  else if (aclass->max_global != 0 && global >= aclass->max_global)
381 >  else if (class->max_global && global >= class->max_global)
382      a_limit_reached = 1;
383 <  else if (aclass->max_ident != 0 && ident >= aclass->max_ident &&
383 >  else if (class->max_ident && ident >= class->max_ident &&
384             client_p->username[0] != '~')
385      a_limit_reached = 1;
386  
387    if (a_limit_reached)
388    {
389 <    if (!IsConfExemptLimits(aconf))
389 >    if (!IsConfExemptLimits(conf))
390        return TOO_MANY;   /* Already at maximum allowed */
391  
392 <    sendto_one(client_p,
393 <               ":%s NOTICE %s :*** Your connection class is full, "
955 <               "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  
961 /* init_ip_hash_table()
962 *
963 * inputs               - NONE
964 * output               - NONE
965 * side effects         - allocate memory for ip_entry(s)
966 *                      - clear the ip hash table
967 */
968 void
969 init_ip_hash_table(void)
970 {
971  ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
972    2 * hard_fdlimit);
973  memset(ip_hash_table, 0, sizeof(ip_hash_table));
974 }
975
976 /* find_or_add_ip()
977 *
978 * inputs       - pointer to struct irc_ssaddr
979 * output       - pointer to a struct ip_entry
980 * side effects -
981 *
982 * If the ip # was not found, a new struct ip_entry is created, and the ip
983 * count set to 0.
984 */
985 static struct ip_entry *
986 find_or_add_ip(struct irc_ssaddr *ip_in)
987 {
988  struct ip_entry *ptr, *newptr;
989  int hash_index = hash_ip(ip_in), res;
990  struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
991 #ifdef IPV6
992  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
993 #endif
994
995  for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
996  {
997 #ifdef IPV6
998    if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
999      continue;
1000    if (ip_in->ss.ss_family == AF_INET6)
1001    {
1002      ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1003      res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1004    }
1005    else
1006 #endif
1007    {
1008      ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1009      res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1010    }
1011    if (res == 0)
1012    {
1013      /* Found entry already in hash, return it. */
1014      return ptr;
1015    }
1016  }
1017
1018  if (ip_entries_count >= 2 * hard_fdlimit)
1019    garbage_collect_ip_entries();
1020
1021  newptr = BlockHeapAlloc(ip_entry_heap);
1022  ip_entries_count++;
1023  memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
1024
1025  newptr->next = ip_hash_table[hash_index];
1026  ip_hash_table[hash_index] = newptr;
1027
1028  return newptr;
1029 }
1030
1031 /* remove_one_ip()
1032 *
1033 * inputs        - unsigned long IP address value
1034 * output        - NONE
1035 * side effects  - The ip address given, is looked up in ip hash table
1036 *                 and number of ip#'s for that ip decremented.
1037 *                 If ip # count reaches 0 and has expired,
1038 *                 the struct ip_entry is returned to the ip_entry_heap
1039 */
1040 void
1041 remove_one_ip(struct irc_ssaddr *ip_in)
1042 {
1043  struct ip_entry *ptr;
1044  struct ip_entry *last_ptr = NULL;
1045  int hash_index = hash_ip(ip_in), res;
1046  struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1047 #ifdef IPV6
1048  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1049 #endif
1050
1051  for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1052  {
1053 #ifdef IPV6
1054    if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1055      continue;
1056    if (ip_in->ss.ss_family == AF_INET6)
1057    {
1058      ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1059      res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1060    }
1061    else
1062 #endif
1063    {
1064      ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1065      res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1066    }
1067    if (res)
1068      continue;
1069    if (ptr->count > 0)
1070      ptr->count--;
1071    if (ptr->count == 0 &&
1072        (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1073    {
1074      if (last_ptr != NULL)
1075        last_ptr->next = ptr->next;
1076      else
1077        ip_hash_table[hash_index] = ptr->next;
1078
1079      BlockHeapFree(ip_entry_heap, ptr);
1080      ip_entries_count--;
1081      return;
1082    }
1083    last_ptr = ptr;
1084  }
1085 }
1086
1087 /* hash_ip()
1088 *
1089 * input        - pointer to an irc_inaddr
1090 * output       - integer value used as index into hash table
1091 * side effects - hopefully, none
1092 */
1093 static int
1094 hash_ip(struct irc_ssaddr *addr)
1095 {
1096  if (addr->ss.ss_family == AF_INET)
1097  {
1098    struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
1099    int hash;
1100    uint32_t ip;
1101
1102    ip   = ntohl(v4->sin_addr.s_addr);
1103    hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
1104    return hash;
1105  }
1106 #ifdef IPV6
1107  else
1108  {
1109    int hash;
1110    struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
1111    uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
1112
1113    hash  = ip[0] ^ ip[3];
1114    hash ^= hash >> 16;  
1115    hash ^= hash >> 8;  
1116    hash  = hash & (IP_HASH_SIZE - 1);
1117    return hash;
1118  }
1119 #else
1120  return 0;
1121 #endif
1122 }
1123
1124 /* count_ip_hash()
1125 *
1126 * inputs        - pointer to counter of number of ips hashed
1127 *               - pointer to memory used for ip hash
1128 * output        - returned via pointers input
1129 * side effects  - NONE
1130 *
1131 * number of hashed ip #'s is counted up, plus the amount of memory
1132 * used in the hash.
1133 */
1134 void
1135 count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
1136 {
1137  struct ip_entry *ptr;
1138  int i;
1139
1140  *number_ips_stored = 0;
1141  *mem_ips_stored    = 0;
1142
1143  for (i = 0; i < IP_HASH_SIZE; i++)
1144  {
1145    for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
1146    {
1147      *number_ips_stored += 1;
1148      *mem_ips_stored += sizeof(struct ip_entry);
1149    }
1150  }
1151 }
1152
1153 /* garbage_collect_ip_entries()
1154 *
1155 * input        - NONE
1156 * output       - NONE
1157 * side effects - free up all ip entries with no connections
1158 */
1159 static void
1160 garbage_collect_ip_entries(void)
1161 {
1162  struct ip_entry *ptr;
1163  struct ip_entry *last_ptr;
1164  struct ip_entry *next_ptr;
1165  int i;
1166
1167  for (i = 0; i < IP_HASH_SIZE; i++)
1168  {
1169    last_ptr = NULL;
1170
1171    for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
1172    {
1173      next_ptr = ptr->next;
1174
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[i] = ptr->next;
1182        BlockHeapFree(ip_entry_heap, ptr);
1183        ip_entries_count--;
1184      }
1185      else
1186        last_ptr = ptr;
1187    }
1188  }
1189 }
1190
399   /* detach_conf()
400   *
401   * inputs       - pointer to client to detach
# Line 1196 | 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;
1203 <  struct ConfItem *conf;
1204 <  struct ClassItem *aclass;
1205 <  struct AccessItem *aconf;
1206 <  struct ConfItem *aclass_conf;
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->localClient->confs.head)
413    {
414 <    conf = ptr->data;
414 >    struct MaskItem *conf = ptr->data;
415  
416 <    if (type == CONF_TYPE || conf->type == type)
417 <    {
418 <      dlinkDelete(ptr, &client_p->localClient->confs);
1215 <      free_dlink_node(ptr);
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 <      switch (conf->type)
421 <      {
1219 <      case CLIENT_TYPE:
1220 <      case OPER_TYPE:
1221 <      case SERVER_TYPE:
1222 <        aconf = map_to_conf(conf);
1223 <
1224 <        assert(aconf->clients > 0);
1225 <
1226 <        if ((aclass_conf = aconf->class_ptr) != NULL)
1227 <        {
1228 <          aclass = map_to_conf(aclass_conf);
1229 <
1230 <          assert(aclass->curr_user_count > 0);
420 >    if (!(conf->type & type))
421 >      continue;
422  
423 <          if (conf->type == CLIENT_TYPE)
424 <            remove_from_cidr_check(&client_p->localClient->ip, aclass);
1234 <          if (--aclass->curr_user_count == 0 && aclass->active == 0)
1235 <            delete_conf_item(aclass_conf);
1236 <        }
423 >    dlinkDelete(ptr, &client_p->localClient->confs);
424 >    free_dlink_node(ptr);
425  
426 <        if (--aconf->clients == 0 && IsConfIllegal(aconf))
427 <          delete_conf_item(conf);
426 >    if (conf->type == CONF_CLIENT)
427 >      remove_from_cidr_check(&client_p->localClient->ip, conf->class);
428  
429 <        break;
430 <      default:
431 <        break;
432 <      }
1245 <
1246 <      if (type != CONF_TYPE)
1247 <        return 0;
429 >    if (--conf->class->ref_count == 0 && conf->class->active == 0)
430 >    {
431 >      class_free(conf->class);
432 >      conf->class = NULL;
433      }
1249  }
434  
435 <  return -1;
435 >    if (--conf->ref_count == 0 && conf->active == 0)
436 >      conf_free(conf);
437 >  }
438   }
439  
440   /* attach_conf()
# Line 1262 | 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 <  struct AccessItem *aconf = map_to_conf(conf);
1268 <  struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1269 <
1270 <  if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
453 >  if (dlinkFind(&client_p->localClient->confs, conf))
454      return 1;
455  
456 <  if (IsConfIllegal(aconf)) /* TBV: can't happen */
457 <    return NOT_AUTHORIZED;
458 <
1276 <  if (conf->type == CLIENT_TYPE)
1277 <    if (cidr_limit_reached(IsConfExemptLimits(aconf),
1278 <                           &client_p->localClient->ip, aclass))
456 >  if (conf->type == CONF_CLIENT)
457 >    if (cidr_limit_reached(IsConfExemptLimits(conf),
458 >                           &client_p->localClient->ip, conf->class))
459        return TOO_MANY;    /* Already at maximum allowed */
460  
461 <  aclass->curr_user_count++;
462 <  aconf->clients++;
461 >  conf->class->ref_count++;
462 >  conf->ref_count++;
463  
464    dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
465  
# Line 1299 | Line 479 | attach_connect_block(struct Client *clie
479                       const char *host)
480   {
481    dlink_node *ptr;
482 <  struct ConfItem *conf;
1303 <  struct AccessItem *aconf;
482 >  struct MaskItem *conf = NULL;
483  
484    assert(client_p != NULL);
485    assert(host != NULL);
# Line 1311 | Line 490 | attach_connect_block(struct Client *clie
490    DLINK_FOREACH(ptr, server_items.head)
491    {
492      conf = ptr->data;
1314    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 1323 | Line 501 | attach_connect_block(struct Client *clie
501    return 0;
502   }
503  
1326 /* find_conf_exact()
1327 *
1328 * inputs       - type of ConfItem
1329 *              - pointer to name to find
1330 *              - pointer to username to find
1331 *              - pointer to host to find
1332 * output       - NULL or pointer to conf found
1333 * side effects - find a conf entry which matches the hostname
1334 *                and has the same name.
1335 */
1336 struct ConfItem *
1337 find_conf_exact(ConfType type, const char *name, const char *user,
1338                const char *host)
1339 {
1340  dlink_node *ptr;
1341  dlink_list *list_p;
1342  struct ConfItem *conf = NULL;
1343  struct AccessItem *aconf;
1344
1345  /* Only valid for OPER_TYPE and ...? */
1346  list_p = map_to_list(type);
1347
1348  DLINK_FOREACH(ptr, (*list_p).head)
1349  {
1350    conf = ptr->data;
1351
1352    if (conf->name == NULL)
1353      continue;
1354    aconf = map_to_conf(conf);
1355    if (aconf->host == NULL)
1356      continue;
1357    if (irccmp(conf->name, name) != 0)
1358      continue;
1359
1360    /*
1361    ** Accept if the *real* hostname (usually sockethost)
1362    ** socket host) matches *either* host or name field
1363    ** of the configuration.
1364    */
1365    if (!match(aconf->host, host) || !match(aconf->user, user))
1366      continue;
1367    if (type == OPER_TYPE)
1368    {
1369      struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1370
1371      if (aconf->clients >= aclass->max_total)
1372        continue;
1373    }
1374
1375    return conf;
1376  }
1377
1378  return NULL;
1379 }
1380
504   /* find_conf_name()
505   *
506   * inputs       - pointer to conf link list to search
# Line 1387 | 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)))
525 >      if (conf->name && (!irccmp(conf->name, name) ||
526 >                         !match(conf->name, name)))
527        return conf;
528      }
529    }
# Line 1415 | Line 538 | find_conf_name(dlink_list *list, const c
538   * side effects - none
539   */
540   static dlink_list *
541 < map_to_list(ConfType type)
541 > map_to_list(enum maskitem_type type)
542   {
543    switch(type)
544    {
545 <  case RXLINE_TYPE:
1423 <    return(&rxconf_items);
1424 <    break;
1425 <  case XLINE_TYPE:
545 >  case CONF_XLINE:
546      return(&xconf_items);
547      break;
548 <  case ULINE_TYPE:
548 >  case CONF_ULINE:
549      return(&uconf_items);
550      break;
551 <  case NRESV_TYPE:
551 >  case CONF_NRESV:
552      return(&nresv_items);
553      break;
554 <  case OPER_TYPE:
554 >  case CONF_CRESV:
555 >    return(&cresv_items);
556 >  case CONF_OPER:
557      return(&oconf_items);
558      break;
559 <  case CLASS_TYPE:
1438 <    return(&class_items);
1439 <    break;
1440 <  case SERVER_TYPE:
559 >  case CONF_SERVER:
560      return(&server_items);
561      break;
562 <  case SERVICE_TYPE:
562 >  case CONF_SERVICE:
563      return(&service_items);
564      break;
565 <  case CLUSTER_TYPE:
565 >  case CONF_CLUSTER:
566      return(&cluster_items);
567      break;
1449  case CONF_TYPE:
1450  case GLINE_TYPE:
1451  case KLINE_TYPE:
1452  case DLINE_TYPE:
1453  case CRESV_TYPE:
568    default:
569      return NULL;
570    }
# Line 1462 | Line 576 | map_to_list(ConfType type)
576   *              - pointer to name string to find
577   *              - pointer to user
578   *              - pointer to host
579 < *              - optional action to match on as well
580 < * output       - NULL or pointer to found struct MatchItem
579 > *              - optional flags to match on as well
580 > * output       - NULL or pointer to found struct MaskItem
581   * side effects - looks for a match on name field
582   */
583 < struct ConfItem *
584 < find_matching_name_conf(ConfType type, const char *name, const char *user,
585 <                        const char *host, int action)
583 > struct MaskItem *
584 > find_matching_name_conf(enum maskitem_type type, const char *name, const char *user,
585 >                        const char *host, unsigned int flags)
586   {
587    dlink_node *ptr=NULL;
588 <  struct ConfItem *conf=NULL;
1475 <  struct AccessItem *aconf=NULL;
1476 <  struct MatchItem *match_item=NULL;
588 >  struct MaskItem *conf=NULL;
589    dlink_list *list_p = map_to_list(type);
590  
591    switch (type)
592    {
593 < #ifdef HAVE_LIBPCRE
1482 <  case RXLINE_TYPE:
1483 <      DLINK_FOREACH(ptr, list_p->head)
1484 <      {
1485 <        conf = ptr->data;
1486 <        assert(conf->regexpname);
1487 <
1488 <        if (!ircd_pcre_exec(conf->regexpname, name))
1489 <          return conf;
1490 <      }
1491 <      break;
1492 < #endif
1493 <  case SERVICE_TYPE:
593 >  case CONF_SERVICE:
594      DLINK_FOREACH(ptr, list_p->head)
595      {
596        conf = ptr->data;
# Line 1502 | Line 602 | find_matching_name_conf(ConfType type, c
602      }
603      break;
604  
605 <  case XLINE_TYPE:
606 <  case ULINE_TYPE:
607 <  case NRESV_TYPE:
605 >  case CONF_XLINE:
606 >  case CONF_ULINE:
607 >  case CONF_NRESV:
608 >  case CONF_CRESV:
609      DLINK_FOREACH(ptr, list_p->head)
610      {
611        conf = ptr->data;
612  
1512      match_item = map_to_conf(conf);
613        if (EmptyString(conf->name))
614 <        continue;
615 <      if ((name != NULL) && match_esc(conf->name, name))
614 >        continue;
615 >      if ((name != NULL) && !match(conf->name, name))
616        {
617 <        if ((user == NULL && (host == NULL)))
618 <          return conf;
619 <        if ((match_item->action & action) != action)
617 >        if ((user == NULL && (host == NULL)))
618 >          return conf;
619 >        if ((conf->flags & flags) != flags)
620            continue;
621 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
622 <          return conf;
623 <        if (match(match_item->user, user) && match(match_item->host, host))
624 <          return conf;
621 >        if (EmptyString(conf->user) || EmptyString(conf->host))
622 >          return conf;
623 >        if (!match(conf->user, user) && !match(conf->host, host))
624 >          return conf;
625        }
626      }
627        break;
628  
629 <  case SERVER_TYPE:
629 >  case CONF_SERVER:
630      DLINK_FOREACH(ptr, list_p->head)
631      {
632        conf = ptr->data;
1533      aconf = map_to_conf(conf);
633  
634 <      if ((name != NULL) && match_esc(name, conf->name))
634 >      if ((name != NULL) && !match(name, conf->name))
635          return conf;
636 <      else if ((host != NULL) && match_esc(host, aconf->host))
636 >      else if ((host != NULL) && !match(host, conf->host))
637          return conf;
638      }
639      break;
640 <  
640 >
641    default:
642      break;
643    }
# Line 1551 | Line 650 | find_matching_name_conf(ConfType type, c
650   *              - pointer to name string to find
651   *              - pointer to user
652   *              - pointer to host
653 < * output       - NULL or pointer to found struct MatchItem
653 > * output       - NULL or pointer to found struct MaskItem
654   * side effects - looks for an exact match on name field
655   */
656 < struct ConfItem *
657 < find_exact_name_conf(ConfType type, const struct Client *who, const char *name,
656 > struct MaskItem *
657 > find_exact_name_conf(enum maskitem_type type, const struct Client *who, const char *name,
658                       const char *user, const char *host)
659   {
660    dlink_node *ptr = NULL;
661 <  struct AccessItem *aconf;
662 <  struct ConfItem *conf;
1564 <  struct MatchItem *match_item;
1565 <  dlink_list *list_p;
1566 <
1567 <  list_p = map_to_list(type);
661 >  struct MaskItem *conf;
662 >  dlink_list *list_p = map_to_list(type);
663  
664    switch(type)
665    {
666 <  case RXLINE_TYPE:
667 <  case XLINE_TYPE:
668 <  case ULINE_TYPE:
669 <  case NRESV_TYPE:
666 >  case CONF_XLINE:
667 >  case CONF_ULINE:
668 >  case CONF_NRESV:
669 >  case CONF_CRESV:
670  
671      DLINK_FOREACH(ptr, list_p->head)
672      {
673        conf = ptr->data;
674 <      match_item = (struct MatchItem *)map_to_conf(conf);
674 >
675        if (EmptyString(conf->name))
676 <        continue;
677 <    
676 >        continue;
677 >
678        if (irccmp(conf->name, name) == 0)
679        {
680 <        if ((user == NULL && (host == NULL)))
681 <          return (conf);
682 <        if (EmptyString(match_item->user) || EmptyString(match_item->host))
683 <          return (conf);
684 <        if (match(match_item->user, user) && match(match_item->host, host))
685 <          return (conf);
680 >        if ((user == NULL && (host == NULL)))
681 >          return conf;
682 >        if (EmptyString(conf->user) || EmptyString(conf->host))
683 >          return conf;
684 >        if (!match(conf->user, user) && !match(conf->host, host))
685 >          return conf;
686        }
687      }
688      break;
689  
690 <  case OPER_TYPE:
690 >  case CONF_OPER:
691      DLINK_FOREACH(ptr, list_p->head)
692      {
693        conf = ptr->data;
1599      aconf = map_to_conf(conf);
694  
695        if (EmptyString(conf->name))
696          continue;
# Line 1605 | Line 699 | find_exact_name_conf(ConfType type, cons
699        {
700          if (!who)
701            return conf;
702 <        if (EmptyString(aconf->user) || EmptyString(aconf->host))
703 <          return conf;
704 <        if (match(aconf->user, who->username))
702 >        if (EmptyString(conf->user) || EmptyString(conf->host))
703 >          return NULL;
704 >        if (!match(conf->user, who->username))
705          {
706 <          switch (aconf->type)
706 >          switch (conf->htype)
707            {
708              case HM_HOST:
709 <              if (match(aconf->host, who->host) || match(aconf->host, who->sockhost))
710 <                return conf;
709 >              if (!match(conf->host, who->host) || !match(conf->host, who->sockhost))
710 >                if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
711 >                  return conf;
712                break;
713              case HM_IPV4:
714                if (who->localClient->aftype == AF_INET)
715 <                if (match_ipv4(&who->localClient->ip, &aconf->addr, aconf->bits))
716 <                  return conf;
715 >                if (match_ipv4(&who->localClient->ip, &conf->addr, conf->bits))
716 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
717 >                    return conf;
718                break;
719   #ifdef IPV6
720              case HM_IPV6:
721                if (who->localClient->aftype == AF_INET6)
722 <                if (match_ipv6(&who->localClient->ip, &aconf->addr, aconf->bits))
723 <                  return conf;
722 >                if (match_ipv6(&who->localClient->ip, &conf->addr, conf->bits))
723 >                  if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
724 >                    return conf;
725                break;
726   #endif
727              default:
# Line 1636 | Line 733 | find_exact_name_conf(ConfType type, cons
733  
734      break;
735  
736 <  case SERVER_TYPE:
736 >  case CONF_SERVER:
737      DLINK_FOREACH(ptr, list_p->head)
738      {
739        conf = ptr->data;
740 <      aconf = (struct AccessItem *)map_to_conf(conf);
740 >
741        if (EmptyString(conf->name))
742 <        continue;
743 <    
742 >        continue;
743 >
744        if (name == NULL)
745        {
746 <        if (EmptyString(aconf->host))
747 <          continue;
748 <        if (irccmp(aconf->host, host) == 0)
749 <          return(conf);
746 >        if (EmptyString(conf->host))
747 >          continue;
748 >        if (irccmp(conf->host, host) == 0)
749 >          return conf;
750        }
751        else if (irccmp(conf->name, name) == 0)
752 <      {
1656 <          return (conf);
1657 <      }
752 >        return conf;
753      }
1659    break;
754  
1661  case CLASS_TYPE:
1662    DLINK_FOREACH(ptr, list_p->head)
1663    {
1664      conf = ptr->data;
1665      if (EmptyString(conf->name))
1666        continue;
1667    
1668      if (irccmp(conf->name, name) == 0)
1669        return (conf);
1670    }
755      break;
756  
757    default:
758      break;
759    }
760 <  return(NULL);
760 >
761 >  return NULL;
762   }
763  
764   /* rehash()
# Line 1685 | Line 770 | find_exact_name_conf(ConfType type, cons
770   int
771   rehash(int sig)
772   {
773 <  if (sig != 0)
773 >  if (sig)
774      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
775 <                         "Got signal SIGHUP, reloading ircd.conf file");
775 >                         "Got signal SIGHUP, reloading configuration file(s)");
776  
777    restart_resolver();
778  
# Line 1698 | Line 783 | rehash(int sig)
783  
784    read_conf_files(0);
785  
786 <  if (ServerInfo.description != NULL)
786 >  if (ServerInfo.description)
787      strlcpy(me.info, ServerInfo.description, sizeof(me.info));
788  
789    load_conf_modules();
790 +  check_conf_klines();
791  
792 <  flush_deleted_I_P();
1707 <
1708 <  rehashed_klines = 1;
1709 < /* XXX */
1710 <  if (ConfigLoggingEntry.use_logging)
1711 <    log_close_all();
1712 <
1713 <  return(0);
792 >  return 0;
793   }
794  
795   /* set_default_conf()
# Line 1728 | Line 807 | set_default_conf(void)
807    /* verify init_class() ran, this should be an unnecessary check
808     * but its not much work.
809     */
810 <  assert(class_default == (struct ConfItem *) class_items.tail->data);
810 >  assert(class_default == class_get_list()->tail->data);
811  
812   #ifdef HAVE_LIBCRYPTO
813 +  ServerInfo.message_digest_algorithm = EVP_sha256();
814    ServerInfo.rsa_private_key = NULL;
815    ServerInfo.rsa_private_key_file = NULL;
816   #endif
# Line 1738 | Line 818 | set_default_conf(void)
818    /* ServerInfo.name is not rehashable */
819    /* ServerInfo.name = ServerInfo.name; */
820    ServerInfo.description = NULL;
821 <  DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
822 <  DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
821 >  ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
822 >  ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
823  
824    memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
825    ServerInfo.specific_ipv4_vhost = 0;
# Line 1747 | Line 827 | set_default_conf(void)
827    ServerInfo.specific_ipv6_vhost = 0;
828  
829    ServerInfo.max_clients = MAXCLIENTS_MAX;
830 <
830 >  ServerInfo.max_nick_length = 9;
831 >  ServerInfo.max_topic_length = 80;
832    ServerInfo.hub = 0;
833    ServerInfo.dns_host.sin_addr.s_addr = 0;
834    ServerInfo.dns_host.sin_port = 0;
835 +
836    AdminInfo.name = NULL;
837    AdminInfo.email = NULL;
838    AdminInfo.description = NULL;
839  
840 <  log_close_all();
840 >  log_del_all();
841  
842    ConfigLoggingEntry.use_logging = 1;
843  
844    ConfigChannel.disable_fake_channels = 0;
845 <  ConfigChannel.restrict_channels = 0;
846 <  ConfigChannel.knock_delay = 300;
845 >  ConfigChannel.invite_client_count = 10;
846 >  ConfigChannel.invite_client_time = 300;
847 >  ConfigChannel.knock_client_count = 1;
848 >  ConfigChannel.knock_client_time = 300;
849    ConfigChannel.knock_delay_channel = 60;
850 <  ConfigChannel.max_chans_per_user = 25;
1767 <  ConfigChannel.max_chans_per_oper = 50;
1768 <  ConfigChannel.quiet_on_ban = 1;
850 >  ConfigChannel.max_channels = 25;
851    ConfigChannel.max_bans = 25;
852    ConfigChannel.default_split_user_count = 0;
853    ConfigChannel.default_split_server_count = 0;
# Line 1776 | Line 858 | set_default_conf(void)
858    ConfigServerHide.links_delay = 300;
859    ConfigServerHide.hidden = 0;
860    ConfigServerHide.hide_servers = 0;
861 <  DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
861 >  ConfigServerHide.hide_services = 0;
862 >  ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
863    ConfigServerHide.hide_server_ips = 0;
864 +  ConfigServerHide.disable_remote_commands = 0;
865  
866 <  
867 <  DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
866 >  ConfigFileEntry.away_count = 2;
867 >  ConfigFileEntry.away_time = 10;
868 >  ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
869    ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
870 +  ConfigFileEntry.cycle_on_host_change = 1;
871    ConfigFileEntry.glines = 0;
872    ConfigFileEntry.gline_time = 12 * 3600;
873    ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
# Line 1792 | Line 878 | set_default_conf(void)
878    ConfigFileEntry.hide_spoof_ips = 1;
879    ConfigFileEntry.ignore_bogus_ts = 0;
880    ConfigFileEntry.disable_auth = 0;
1795  ConfigFileEntry.disable_remote = 0;
881    ConfigFileEntry.kill_chase_time_limit = 90;
882    ConfigFileEntry.default_floodcount = 8;
883    ConfigFileEntry.failed_oper_notice = 1;
# Line 1806 | Line 891 | set_default_conf(void)
891    ConfigFileEntry.anti_spam_exit_message_time = 0;
892    ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
893    ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
894 <  ConfigFileEntry.warn_no_nline = 1;
894 >  ConfigFileEntry.warn_no_connect_block = 1;
895 >  ConfigFileEntry.stats_e_disabled = 0;
896    ConfigFileEntry.stats_o_oper_only = 0;
897 <  ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
898 <  ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
897 >  ConfigFileEntry.stats_k_oper_only = 1;  /* 1 = masked */
898 >  ConfigFileEntry.stats_i_oper_only = 1;  /* 1 = masked */
899    ConfigFileEntry.stats_P_oper_only = 0;
900 +  ConfigFileEntry.stats_u_oper_only = 0;
901    ConfigFileEntry.caller_id_wait = 60;
902    ConfigFileEntry.opers_bypass_callerid = 0;
903    ConfigFileEntry.pace_wait = 10;
# Line 1822 | Line 909 | set_default_conf(void)
909    ConfigFileEntry.oper_pass_resv = 1;
910    ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
911    ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
912 <  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
913 <    UMODE_OPERWALL | UMODE_WALLOP;
914 <  ConfigFileEntry.use_egd = 0;
1828 <  ConfigFileEntry.egdpool_path = NULL;
1829 <  ConfigFileEntry.throttle_time = 10;
912 >  ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE | UMODE_WALLOP;
913 >  ConfigFileEntry.throttle_count = 1;
914 >  ConfigFileEntry.throttle_time = 1;
915   }
916  
917   static void
# Line 1839 | Line 924 | validate_conf(void)
924      ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
925  
926    if (ServerInfo.network_name == NULL)
927 <    DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
927 >    ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
928  
929    if (ServerInfo.network_desc == NULL)
930 <    DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
930 >    ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
931  
932    if (ConfigFileEntry.service_name == NULL)
933 <    DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
933 >    ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
934  
935    ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
936   }
937  
938 < /* read_conf()
938 > /* read_conf()
939   *
940   * inputs       - file descriptor pointing to config file to use
941   * output       - None
# Line 1861 | Line 946 | read_conf(FILE *file)
946   {
947    lineno = 0;
948  
949 <  set_default_conf(); /* Set default values prior to conf parsing */
949 >  set_default_conf();  /* Set default values prior to conf parsing */
950    conf_parser_ctx.pass = 1;
951 <  yyparse();          /* pick up the classes first */
951 >  yyparse();  /* Pick up the classes first */
952  
953    rewind(file);
954  
955    conf_parser_ctx.pass = 2;
956 <  yyparse();          /* Load the values from the conf */
957 <  validate_conf();    /* Check to make sure some values are still okay. */
958 <                      /* Some global values are also loaded here. */
959 <  check_class();      /* Make sure classes are valid */
956 >  yyparse();  /* Load the values from the conf */
957 >  validate_conf();  /* Check to make sure some values are still okay. */
958 >                    /* Some global values are also loaded here. */
959 >  class_delete_marked();  /* Delete unused classes that are marked for deletion */
960   }
961  
962   /* lookup_confhost()
# Line 1879 | Line 964 | read_conf(FILE *file)
964   * start DNS lookups of all hostnames in the conf
965   * line and convert an IP addresses in a.b.c.d number for to IP#s.
966   */
967 < static void
968 < lookup_confhost(struct ConfItem *conf)
967 > void
968 > lookup_confhost(struct MaskItem *conf)
969   {
1885  struct AccessItem *aconf;
970    struct addrinfo hints, *res;
971  
972 <  aconf = map_to_conf(conf);
973 <
1890 <  if (has_wildcards(aconf->host))
1891 <  {
1892 <    ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
1893 <         aconf->host, conf->name);
1894 <    return;
1895 <  }
1896 <
1897 <  /* Do name lookup now on hostnames given and store the
972 >  /*
973 >   * Do name lookup now on hostnames given and store the
974     * ip numbers in conf structure.
975     */
976    memset(&hints, 0, sizeof(hints));
# Line 1905 | Line 981 | lookup_confhost(struct ConfItem *conf)
981    /* Get us ready for a bind() and don't bother doing dns lookup */
982    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
983  
984 <  if (getaddrinfo(aconf->host, NULL, &hints, &res))
984 >  if (getaddrinfo(conf->host, NULL, &hints, &res))
985    {
986 <    conf_dns_lookup(aconf);
986 >    conf_dns_lookup(conf);
987      return;
988    }
989  
990 <  assert(res != NULL);
990 >  assert(res);
991 >
992 >  memcpy(&conf->addr, res->ai_addr, res->ai_addrlen);
993 >  conf->addr.ss_len = res->ai_addrlen;
994 >  conf->addr.ss.ss_family = res->ai_family;
995  
1916  memcpy(&aconf->addr, res->ai_addr, res->ai_addrlen);
1917  aconf->addr.ss_len = res->ai_addrlen;
1918  aconf->addr.ss.ss_family = res->ai_family;
996    freeaddrinfo(res);
997   }
998  
# Line 1929 | Line 1006 | lookup_confhost(struct ConfItem *conf)
1006   int
1007   conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1008   {
1009 <  struct ip_entry *ip_found;
1010 <  struct AccessItem *aconf = find_dline_conf(addr, aftype);
1009 >  struct ip_entry *ip_found = NULL;
1010 >  struct MaskItem *conf = find_dline_conf(addr, aftype);
1011  
1012    /* DLINE exempt also gets you out of static limits/pacing... */
1013 <  if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1013 >  if (conf && (conf->type == CONF_EXEMPT))
1014      return 0;
1015  
1016 <  if (aconf != NULL)
1016 >  if (conf)
1017      return BANNED_CLIENT;
1018  
1019 <  ip_found = find_or_add_ip(addr);
1019 >  ip_found = ipcache_find_or_add_address(addr);
1020  
1021 <  if ((CurrentTime - ip_found->last_attempt) <
1945 <      ConfigFileEntry.throttle_time)
1021 >  if ((CurrentTime - ip_found->last_attempt) < ConfigFileEntry.throttle_time)
1022    {
1023 <    ip_found->last_attempt = CurrentTime;
1024 <    return TOO_FAST;
1023 >    if (ip_found->connection_count >= ConfigFileEntry.throttle_count)
1024 >      return TOO_FAST;
1025 >
1026 >    ++ip_found->connection_count;
1027    }
1028 +  else
1029 +    ip_found->connection_count = 1;
1030  
1031    ip_found->last_attempt = CurrentTime;
1032    return 0;
1033   }
1034  
1955 static struct AccessItem *
1956 find_regexp_kline(const char *uhi[])
1957 {
1958 #ifdef HAVE_LIBPCRE
1959  const dlink_node *ptr = NULL;
1960
1961  DLINK_FOREACH(ptr, rkconf_items.head)
1962  {
1963    struct AccessItem *aptr = map_to_conf(ptr->data);
1964
1965    assert(aptr->regexuser);
1966    assert(aptr->regexhost);
1967
1968    if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
1969        (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
1970         !ircd_pcre_exec(aptr->regexhost, uhi[2])))
1971      return aptr;
1972  }
1973 #endif
1974  return NULL;
1975 }
1976
1977 /* find_kill()
1978 *
1979 * inputs       - pointer to client structure
1980 * output       - pointer to struct AccessItem if found
1981 * side effects - See if this user is klined already,
1982 *                and if so, return struct AccessItem pointer
1983 */
1984 struct AccessItem *
1985 find_kill(struct Client *client_p)
1986 {
1987  struct AccessItem *aconf = NULL;
1988  const char *uhi[3];
1989
1990  uhi[0] = client_p->username;
1991  uhi[1] = client_p->host;
1992  uhi[2] = client_p->sockhost;
1993
1994  assert(client_p != NULL);
1995
1996  aconf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1997                               CONF_KLINE, client_p->localClient->aftype,
1998                               client_p->username, NULL, 1);
1999  if (aconf == NULL)
2000    aconf = find_regexp_kline(uhi);
2001
2002  return aconf;
2003 }
2004
2005 struct AccessItem *
2006 find_gline(struct Client *client_p)
2007 {
2008  struct AccessItem *aconf;
2009
2010  assert(client_p != NULL);
2011
2012  aconf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
2013                               CONF_GLINE, client_p->localClient->aftype,
2014                               client_p->username, NULL, 1);
2015  return aconf;
2016 }
2017
2018 /* add_temp_line()
2019 *
2020 * inputs        - pointer to struct ConfItem
2021 * output        - none
2022 * Side effects  - links in given struct ConfItem into
2023 *                 temporary *line link list
2024 */
2025 void
2026 add_temp_line(struct ConfItem *conf)
2027 {
2028  if (conf->type == XLINE_TYPE)
2029  {
2030    conf->flags |= CONF_FLAGS_TEMPORARY;
2031    dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2032  }
2033  else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2034  {
2035    conf->flags |= CONF_FLAGS_TEMPORARY;
2036    dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2037  }
2038 }
2039
1035   /* cleanup_tklines()
1036   *
1037   * inputs       - NONE
# Line 2048 | Line 1043 | void
1043   cleanup_tklines(void *notused)
1044   {
1045    hostmask_expire_temporary();
1046 <  expire_tklines(&temporary_xlines);
1047 <  expire_tklines(&temporary_resv);
1046 >  expire_tklines(&xconf_items);
1047 >  expire_tklines(&nresv_items);
1048 >  expire_tklines(&cresv_items);
1049   }
1050  
1051   /* expire_tklines()
# Line 2061 | Line 1057 | cleanup_tklines(void *notused)
1057   static void
1058   expire_tklines(dlink_list *tklist)
1059   {
1060 <  dlink_node *ptr;
1061 <  dlink_node *next_ptr;
2066 <  struct ConfItem *conf;
2067 <  struct MatchItem *xconf;
2068 <  struct MatchItem *nconf;
2069 <  struct ResvChannel *cconf;
1060 >  dlink_node *ptr = NULL, *ptr_next = NULL;
1061 >  struct MaskItem *conf = NULL;
1062  
1063 <  DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
1063 >  DLINK_FOREACH_SAFE(ptr, ptr_next, tklist->head)
1064    {
1065      conf = ptr->data;
1066  
1067 <    if (conf->type == XLINE_TYPE)
1067 >    if (!conf->until || conf->until > CurrentTime)
1068 >      continue;
1069 >
1070 >    if (conf->type == CONF_XLINE)
1071      {
1072 <      xconf = (struct MatchItem *)map_to_conf(conf);
1073 <      if (xconf->hold <= CurrentTime)
2079 <      {
2080 <        if (ConfigFileEntry.tkline_expire_notices)
2081 <          sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1072 >      if (ConfigFileEntry.tkline_expire_notices)
1073 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1074                                 "Temporary X-line for [%s] expired", conf->name);
1075 <        dlinkDelete(ptr, tklist);
2084 <        free_dlink_node(ptr);
2085 <        delete_conf_item(conf);
2086 <      }
1075 >      conf_free(conf);
1076      }
1077 <    else if (conf->type == NRESV_TYPE)
1077 >    else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1078      {
1079 <      nconf = (struct MatchItem *)map_to_conf(conf);
1080 <      if (nconf->hold <= CurrentTime)
2092 <      {
2093 <        if (ConfigFileEntry.tkline_expire_notices)
2094 <          sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1079 >      if (ConfigFileEntry.tkline_expire_notices)
1080 >        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1081                                 "Temporary RESV for [%s] expired", conf->name);
1082 <        dlinkDelete(ptr, tklist);
2097 <        free_dlink_node(ptr);
2098 <        delete_conf_item(conf);
2099 <      }
2100 <    }
2101 <    else if (conf->type == CRESV_TYPE)
2102 <    {
2103 <      cconf = (struct ResvChannel *)map_to_conf(conf);
2104 <      if (cconf->hold <= CurrentTime)
2105 <      {
2106 <        if (ConfigFileEntry.tkline_expire_notices)
2107 <          sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2108 <                               "Temporary RESV for [%s] expired", cconf->name);
2109 <        delete_channel_resv(cconf);
2110 <      }
1082 >      conf_free(conf);
1083      }
1084    }
1085   }
# Line 2120 | Line 1092 | expire_tklines(dlink_list *tklist)
1092   */
1093   static const struct oper_privs
1094   {
1095 <  const unsigned int oprivs;
1095 >  const unsigned int flag;
1096    const unsigned char c;
1097   } flag_list[] = {
1098 <  { OPER_FLAG_ADMIN,       'A' },
1099 <  { OPER_FLAG_REMOTEBAN,   'B' },
1100 <  { OPER_FLAG_DIE,         'D' },
1101 <  { OPER_FLAG_GLINE,       'G' },
1102 <  { OPER_FLAG_REHASH,      'H' },
1103 <  { OPER_FLAG_K,           'K' },
1104 <  { OPER_FLAG_OPERWALL,    'L' },
1105 <  { OPER_FLAG_N,           'N' },
1106 <  { OPER_FLAG_GLOBAL_KILL, 'O' },
1107 <  { OPER_FLAG_REMOTE,      'R' },
1108 <  { OPER_FLAG_OPER_SPY,    'S' },
1109 <  { OPER_FLAG_UNKLINE,     'U' },
1110 <  { OPER_FLAG_X,           'X' },
1098 >  { OPER_FLAG_ADMIN,          'A' },
1099 >  { OPER_FLAG_REMOTEBAN,      'B' },
1100 >  { OPER_FLAG_DIE,            'D' },
1101 >  { OPER_FLAG_GLINE,          'G' },
1102 >  { OPER_FLAG_REHASH,         'H' },
1103 >  { OPER_FLAG_KLINE,          'K' },
1104 >  { OPER_FLAG_KILL,           'N' },
1105 >  { OPER_FLAG_KILL_REMOTE,    'O' },
1106 >  { OPER_FLAG_CONNECT,        'P' },
1107 >  { OPER_FLAG_CONNECT_REMOTE, 'Q' },
1108 >  { OPER_FLAG_SQUIT,          'R' },
1109 >  { OPER_FLAG_SQUIT_REMOTE,   'S' },
1110 >  { OPER_FLAG_UNKLINE,        'U' },
1111 >  { OPER_FLAG_XLINE,          'X' },
1112    { 0, '\0' }
1113   };
1114  
1115   char *
1116   oper_privs_as_string(const unsigned int port)
1117   {
1118 <  static char privs_out[16];
1118 >  static char privs_out[IRCD_BUFSIZE];
1119    char *privs_ptr = privs_out;
2147  unsigned int i = 0;
1120  
1121 <  for (; flag_list[i].oprivs; ++i)
1121 >  for (const struct oper_privs *opriv = flag_list; opriv->flag; ++opriv)
1122    {
1123 <    if (port & flag_list[i].oprivs)
1124 <      *privs_ptr++ = flag_list[i].c;
1123 >    if (port & opriv->flag)
1124 >      *privs_ptr++ = opriv->c;
1125      else
1126 <      *privs_ptr++ = ToLowerTab[flag_list[i].c];
1126 >      *privs_ptr++ = ToLower(opriv->c);
1127    }
1128  
1129    *privs_ptr = '\0';
# Line 2160 | Line 1132 | oper_privs_as_string(const unsigned int
1132   }
1133  
1134   /*
1135 < * Input: A client to find the active oper{} name for.
1135 > * Input: A client to find the active operator {} name for.
1136   * Output: The nick!user@host{oper} of the oper.
1137   *         "oper" is server name for remote opers
1138   * Side effects: None.
# Line 2168 | Line 1140 | oper_privs_as_string(const unsigned int
1140   const char *
1141   get_oper_name(const struct Client *client_p)
1142   {
1143 <  dlink_node *cnode = NULL;
1143 >  const dlink_node *cnode = NULL;
1144    /* +5 for !,@,{,} and null */
1145    static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
1146  
# Line 2176 | Line 1148 | get_oper_name(const struct Client *clien
1148    {
1149      if ((cnode = client_p->localClient->confs.head))
1150      {
1151 <      struct ConfItem *conf = cnode->data;
2180 <      const struct AccessItem *aconf = map_to_conf(conf);
1151 >      const struct MaskItem *conf = cnode->data;
1152  
1153 <      if (IsConfOperator(aconf))
1153 >      if (IsConfOperator(conf))
1154        {
1155 <        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1155 >        snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1156                   client_p->username, client_p->host, conf->name);
1157 <        return buffer;
1157 >        return buffer;
1158        }
1159      }
1160  
1161 <    /* Probably should assert here for now. If there is an oper out there
1162 <     * with no oper{} conf attached, it would be good for us to know...
1161 >    /*
1162 >     * Probably should assert here for now. If there is an oper out there
1163 >     * with no operator {} conf attached, it would be good for us to know...
1164       */
1165 <    assert(0); /* Oper without oper conf! */
1165 >    assert(0);  /* Oper without oper conf! */
1166    }
1167  
1168    snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1169 <           client_p->username, client_p->host, client_p->servptr->name);
1169 >           client_p->username, client_p->host, client_p->servptr->name);
1170    return buffer;
1171   }
1172  
# Line 2207 | Line 1179 | get_oper_name(const struct Client *clien
1179   void
1180   read_conf_files(int cold)
1181   {
1182 <  const char *filename;
1183 <  char chanmodes[32];
1184 <  char chanlimit[32];
1182 >  const char *filename = NULL;
1183 >  char chanmodes[IRCD_BUFSIZE] = "";
1184 >  char chanlimit[IRCD_BUFSIZE] = "";
1185  
1186    conf_parser_ctx.boot = cold;
1187 <  filename = get_conf_name(CONF_TYPE);
1187 >  filename = ConfigFileEntry.configfile;
1188  
1189    /* We need to know the initial filename for the yyerror() to report
1190       FIXME: The full path is in conffilenamebuf first time since we
1191 <             dont know anything else
1191 >             don't know anything else
1192  
1193 <     - Gozem 2002-07-21
1193 >     - Gozem 2002-07-21
1194    */
1195    strlcpy(conffilebuf, filename, sizeof(conffilebuf));
1196  
# Line 2233 | Line 1205 | read_conf_files(int cold)
1205      else
1206      {
1207        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1208 <                           "Unable to read configuration file '%s': %s",
1209 <                           filename, strerror(errno));
1208 >                           "Unable to read configuration file '%s': %s",
1209 >                           filename, strerror(errno));
1210        return;
1211      }
1212    }
# Line 2245 | Line 1217 | read_conf_files(int cold)
1217    read_conf(conf_parser_ctx.conf_file);
1218    fclose(conf_parser_ctx.conf_file);
1219  
1220 +  log_reopen_all();
1221 +
1222 +  add_isupport("NICKLEN", NULL, ServerInfo.max_nick_length);
1223    add_isupport("NETWORK", ServerInfo.network_name, -1);
1224 <  snprintf(chanmodes, sizeof(chanmodes), "beI:%d",
1225 <           ConfigChannel.max_bans);
1224 >
1225 >  snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1226    add_isupport("MAXLIST", chanmodes, -1);
1227    add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
2253
1228    add_isupport("CHANTYPES", "#", -1);
1229  
1230    snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1231 <           ConfigChannel.max_chans_per_user);
1231 >           ConfigChannel.max_channels);
1232    add_isupport("CHANLIMIT", chanlimit, -1);
1233 <  snprintf(chanmodes, sizeof(chanmodes), "%s",
1234 <           "beI,k,l,imnprstORS");
1235 <  add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2262 <
2263 <  add_isupport("EXCEPTS", "e", -1);
2264 <  add_isupport("INVEX", "I", -1);
1233 >  snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,cimnprstMORS");
1234 >  add_isupport("CHANNELLEN", NULL, CHANNELLEN);
1235 >  add_isupport("TOPICLEN", NULL, ServerInfo.max_topic_length);
1236    add_isupport("CHANMODES", chanmodes, -1);
1237  
1238    /*
# Line 2269 | Line 1240 | read_conf_files(int cold)
1240     * on strlen(form_str(RPL_ISUPPORT))
1241     */
1242    rebuild_isupport_message_line();
2272
2273  parse_conf_file(KLINE_TYPE, cold);
2274  parse_conf_file(DLINE_TYPE, cold);
2275  parse_conf_file(XLINE_TYPE, cold);
2276  parse_conf_file(NRESV_TYPE, cold);
2277  parse_conf_file(CRESV_TYPE, cold);
2278 }
2279
2280 /* parse_conf_file()
2281 *
2282 * inputs       - type of conf file to parse
2283 * output       - none
2284 * side effects - conf file for givenconf type is opened and read then parsed
2285 */
2286 static void
2287 parse_conf_file(int type, int cold)
2288 {
2289  FILE *file = NULL;
2290  const char *filename = get_conf_name(type);
2291
2292  if ((file = fopen(filename, "r")) == NULL)
2293  {
2294    if (cold)
2295      ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2296           filename, strerror(errno));
2297    else
2298      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2299                    "Unable to read configuration file '%s': %s",
2300                           filename, strerror(errno));
2301  }
2302  else
2303  {
2304    parse_csv_file(file, type);
2305    fclose(file);
2306  }
1243   }
1244  
1245   /* clear_out_old_conf()
# Line 2316 | Line 1252 | static void
1252   clear_out_old_conf(void)
1253   {
1254    dlink_node *ptr = NULL, *next_ptr = NULL;
1255 <  struct ConfItem *conf;
2320 <  struct AccessItem *aconf;
2321 <  struct ClassItem *cltmp;
1255 >  struct MaskItem *conf;
1256    dlink_list *free_items [] = {
1257      &server_items,   &oconf_items,
1258 <     &uconf_items,   &xconf_items, &rxconf_items, &rkconf_items,
1259 <     &nresv_items, &cluster_items,  &service_items, NULL
1258 >     &uconf_items,   &xconf_items,
1259 >     &nresv_items, &cluster_items,  &service_items, &cresv_items, NULL
1260    };
1261  
1262    dlink_list ** iterator = free_items; /* C is dumb */
# Line 2330 | Line 1264 | clear_out_old_conf(void)
1264    /* We only need to free anything allocated by yyparse() here.
1265     * Resetting structs, etc, is taken care of by set_default_conf().
1266     */
1267 <  
1267 >
1268    for (; *iterator != NULL; iterator++)
1269    {
1270      DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1271      {
1272        conf = ptr->data;
2339      /* XXX This is less than pretty */
2340      if (conf->type == SERVER_TYPE)
2341      {
2342        aconf = map_to_conf(conf);
1273  
1274 <        if (aconf->clients != 0)
2345 <        {
2346 <          SetConfIllegal(aconf);
2347 <          dlinkDelete(&conf->node, &server_items);
2348 <        }
2349 <        else
2350 <        {
2351 <          delete_conf_item(conf);
2352 <        }
2353 <      }
2354 <      else if (conf->type == OPER_TYPE)
2355 <      {
2356 <        aconf = map_to_conf(conf);
1274 >      dlinkDelete(&conf->node, map_to_list(conf->type));
1275  
1276 <        if (aconf->clients != 0)
1277 <        {
2360 <          SetConfIllegal(aconf);
2361 <          dlinkDelete(&conf->node, &oconf_items);
2362 <        }
2363 <        else
2364 <        {
2365 <          delete_conf_item(conf);
2366 <        }
2367 <      }
2368 <      else if (conf->type == XLINE_TYPE  ||
2369 <               conf->type == RXLINE_TYPE ||
2370 <               conf->type == RKLINE_TYPE)
1276 >      /* XXX This is less than pretty */
1277 >      if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1278        {
1279 <        /* temporary (r)xlines are also on
1280 <         * the (r)xconf items list */
2374 <        if (conf->flags & CONF_FLAGS_TEMPORARY)
2375 <          continue;
2376 <
2377 <        delete_conf_item(conf);
1279 >        if (!conf->ref_count)
1280 >          conf_free(conf);
1281        }
1282 <      else
1282 >      else if (conf->type == CONF_XLINE)
1283        {
1284 <          delete_conf_item(conf);
1284 >        if (!conf->until)
1285 >          conf_free(conf);
1286        }
1287 +      else
1288 +        conf_free(conf);
1289      }
1290    }
1291  
1292 +  motd_clear();
1293 +
1294    /*
1295     * don't delete the class table, rather mark all entries
1296 <   * for deletion. The table is cleaned up by check_class. - avalon
1296 >   * for deletion. The table is cleaned up by class_delete_marked. - avalon
1297     */
1298 <  DLINK_FOREACH(ptr, class_items.head)
2391 <  {
2392 <    cltmp = map_to_conf(ptr->data);
2393 <
2394 <    if (ptr != class_items.tail)  /* never mark the "default" class */
2395 <      cltmp->active = 0;
2396 <  }
1298 >  class_mark_for_deletion();
1299  
1300    clear_out_address_conf();
1301  
# Line 2407 | Line 1309 | clear_out_old_conf(void)
1309    ServerInfo.network_name = NULL;
1310    MyFree(ServerInfo.network_desc);
1311    ServerInfo.network_desc = NULL;
2410  MyFree(ConfigFileEntry.egdpool_path);
2411  ConfigFileEntry.egdpool_path = NULL;
1312   #ifdef HAVE_LIBCRYPTO
1313 <  if (ServerInfo.rsa_private_key != NULL)
1313 >  if (ServerInfo.rsa_private_key)
1314    {
1315      RSA_free(ServerInfo.rsa_private_key);
1316      ServerInfo.rsa_private_key = NULL;
# Line 2418 | Line 1318 | clear_out_old_conf(void)
1318  
1319    MyFree(ServerInfo.rsa_private_key_file);
1320    ServerInfo.rsa_private_key_file = NULL;
2421
2422  if (ServerInfo.server_ctx)
2423    SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
2424                                               SSL_OP_NO_SSLv3|
2425                                               SSL_OP_NO_TLSv1);
2426  if (ServerInfo.client_ctx)
2427    SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
2428                                               SSL_OP_NO_SSLv3|
2429                                               SSL_OP_NO_TLSv1);
1321   #endif
1322  
2432  /* clean out old resvs from the conf */
2433  clear_conf_resv();
2434
1323    /* clean out AdminInfo */
1324    MyFree(AdminInfo.name);
1325    AdminInfo.name = NULL;
# Line 2440 | Line 1328 | clear_out_old_conf(void)
1328    MyFree(AdminInfo.description);
1329    AdminInfo.description = NULL;
1330  
2443  /* operator{} and class{} blocks are freed above */
1331    /* clean out listeners */
1332    close_listeners();
1333  
2447  /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2448   * exempt{} and gecos{} blocks are freed above too
2449   */
2450
1334    /* clean out general */
1335    MyFree(ConfigFileEntry.service_name);
1336    ConfigFileEntry.service_name = NULL;
2454
2455  delete_isupport("INVEX");
2456  delete_isupport("EXCEPTS");
2457 }
2458
2459 /* flush_deleted_I_P()
2460 *
2461 * inputs       - none
2462 * output       - none
2463 * side effects - This function removes I/P conf items
2464 */
2465 static void
2466 flush_deleted_I_P(void)
2467 {
2468  dlink_node *ptr;
2469  dlink_node *next_ptr;
2470  struct ConfItem *conf;
2471  struct AccessItem *aconf;
2472  dlink_list * free_items [] = {
2473    &server_items, &oconf_items, NULL
2474  };
2475  dlink_list ** iterator = free_items; /* C is dumb */
2476
2477  /* flush out deleted I and P lines
2478   * although still in use.
2479   */
2480  for (; *iterator != NULL; iterator++)
2481  {
2482    DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2483    {
2484      conf = ptr->data;
2485      aconf = (struct AccessItem *)map_to_conf(conf);
2486
2487      if (IsConfIllegal(aconf))
2488      {
2489        dlinkDelete(ptr, *iterator);
2490
2491        if (aconf->clients == 0)
2492          delete_conf_item(conf);
2493      }
2494    }
2495  }
2496 }
2497
2498 /* get_conf_name()
2499 *
2500 * inputs       - type of conf file to return name of file for
2501 * output       - pointer to filename for type of conf
2502 * side effects - none
2503 */
2504 const char *
2505 get_conf_name(ConfType type)
2506 {
2507  switch (type)
2508  {
2509    case CONF_TYPE:
2510      return ConfigFileEntry.configfile;
2511      break;
2512    case KLINE_TYPE:
2513      return ConfigFileEntry.klinefile;
2514      break;
2515    case DLINE_TYPE:
2516      return ConfigFileEntry.dlinefile;
2517      break;
2518    case XLINE_TYPE:
2519      return ConfigFileEntry.xlinefile;
2520      break;
2521    case CRESV_TYPE:
2522      return ConfigFileEntry.cresvfile;
2523      break;
2524    case NRESV_TYPE:
2525      return ConfigFileEntry.nresvfile;
2526      break;
2527    default:
2528      return NULL;  /* This should NEVER HAPPEN since we call this function
2529                       only with the above values, this will cause us to core
2530                       at some point if this happens so we know where it was */
2531  }
2532 }
2533
2534 #define BAD_PING (-1)
2535
2536 /* get_conf_ping()
2537 *
2538 * inputs       - pointer to struct AccessItem
2539 *              - pointer to a variable that receives ping warning time
2540 * output       - ping frequency
2541 * side effects - NONE
2542 */
2543 static int
2544 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2545 {
2546  struct ClassItem *aclass;
2547  struct AccessItem *aconf;
2548
2549  if (conf != NULL)
2550  {
2551    aconf = (struct AccessItem *)map_to_conf(conf);
2552    if (aconf->class_ptr != NULL)
2553    {
2554      aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2555      *pingwarn = aclass->ping_warning;
2556      return aclass->ping_freq;
2557    }
2558  }
2559
2560  return BAD_PING;
2561 }
2562
2563 /* get_client_class()
2564 *
2565 * inputs       - pointer to client struct
2566 * output       - pointer to name of class
2567 * side effects - NONE
2568 */
2569 const char *
2570 get_client_class(struct Client *target_p)
2571 {
2572  dlink_node *cnode = NULL;
2573  struct AccessItem *aconf = NULL;
2574
2575  assert(!IsMe(target_p));
2576
2577  if ((cnode = target_p->localClient->confs.head))
2578  {
2579    struct ConfItem *conf = cnode->data;
2580
2581    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2582          (conf->type == OPER_TYPE));
2583
2584    aconf = map_to_conf(conf);
2585    if (aconf->class_ptr != NULL)
2586      return aconf->class_ptr->name;
2587  }
2588
2589  return "default";
2590 }
2591
2592 /* get_client_ping()
2593 *
2594 * inputs       - pointer to client struct
2595 *              - pointer to a variable that receives ping warning time
2596 * output       - ping frequency
2597 * side effects - NONE
2598 */
2599 int
2600 get_client_ping(struct Client *target_p, int *pingwarn)
2601 {
2602  int ping = 0;
2603  dlink_node *cnode = NULL;
2604
2605  if ((cnode = target_p->localClient->confs.head))
2606  {
2607    struct ConfItem *conf = cnode->data;
2608
2609    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2610          (conf->type == OPER_TYPE));
2611
2612    ping = get_conf_ping(conf, pingwarn);
2613    if (ping > 0)
2614      return ping;
2615  }
2616
2617  *pingwarn = 0;
2618  return DEFAULT_PINGFREQUENCY;
2619 }
2620
2621 /* find_class()
2622 *
2623 * inputs       - string name of class
2624 * output       - corresponding Class pointer
2625 * side effects - NONE
2626 */
2627 struct ConfItem *
2628 find_class(const char *classname)
2629 {
2630  struct ConfItem *conf;
2631
2632  if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2633    return conf;
2634
2635  return class_default;
2636 }
2637
2638 /* check_class()
2639 *
2640 * inputs       - NONE
2641 * output       - NONE
2642 * side effects -
2643 */
2644 void
2645 check_class(void)
2646 {
2647  dlink_node *ptr = NULL, *next_ptr = NULL;
2648
2649  DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2650  {
2651    struct ClassItem *aclass = map_to_conf(ptr->data);
2652
2653    if (!aclass->active && !aclass->curr_user_count)
2654    {
2655      destroy_cidr_class(aclass);
2656      delete_conf_item(ptr->data);
2657    }
2658  }
2659 }
2660
2661 /* init_class()
2662 *
2663 * inputs       - NONE
2664 * output       - NONE
2665 * side effects -
2666 */
2667 void
2668 init_class(void)
2669 {
2670  struct ClassItem *aclass;
2671
2672  class_default = make_conf_item(CLASS_TYPE);
2673
2674  aclass = map_to_conf(class_default);
2675  aclass->active = 1;
2676  DupString(class_default->name, "default");
2677  aclass->con_freq  = DEFAULT_CONNECTFREQUENCY;
2678  aclass->ping_freq = DEFAULT_PINGFREQUENCY;
2679  aclass->max_total = MAXIMUM_LINKS_DEFAULT;
2680  aclass->max_sendq = DEFAULT_SENDQ;
2681  aclass->max_recvq = DEFAULT_RECVQ;
2682
2683  client_check_cb = register_callback("check_client", check_client);
2684 }
2685
2686 /* get_sendq()
2687 *
2688 * inputs       - pointer to client
2689 * output       - sendq for this client as found from its class
2690 * side effects - NONE
2691 */
2692 unsigned int
2693 get_sendq(struct Client *client_p)
2694 {
2695  unsigned int sendq = DEFAULT_SENDQ;
2696  dlink_node *cnode;
2697  struct ConfItem *class_conf;
2698  struct ClassItem *aclass;
2699  struct AccessItem *aconf;
2700
2701  assert(!IsMe(client_p));
2702
2703  if ((cnode = client_p->localClient->confs.head))
2704  {
2705    struct ConfItem *conf = cnode->data;
2706
2707    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2708          (conf->type == OPER_TYPE));
2709
2710    aconf = map_to_conf(conf);
2711
2712    if ((class_conf = aconf->class_ptr) == NULL)
2713      return DEFAULT_SENDQ; /* TBV: shouldn't be possible at all */
2714
2715    aclass = map_to_conf(class_conf);
2716    sendq = aclass->max_sendq;
2717    return sendq;
2718  }
2719
2720  /* XXX return a default?
2721   * if here, then there wasn't an attached conf with a sendq
2722   * that is very bad -Dianora
2723   */
2724  return DEFAULT_SENDQ;
2725 }
2726
2727 unsigned int
2728 get_recvq(struct Client *client_p)
2729 {
2730  unsigned int recvq = DEFAULT_RECVQ;
2731  dlink_node *cnode;
2732  struct ConfItem *class_conf;
2733  struct ClassItem *aclass;
2734  struct AccessItem *aconf;
2735
2736  assert(!IsMe(client_p));
2737
2738  if ((cnode = client_p->localClient->confs.head))
2739  {
2740    struct ConfItem *conf = cnode->data;
2741
2742    assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2743          (conf->type == OPER_TYPE));
2744
2745    aconf = map_to_conf(conf);
2746
2747    if ((class_conf = aconf->class_ptr) == NULL)
2748      return DEFAULT_RECVQ; /* TBV: shouldn't be possible at all */
2749
2750    aclass = map_to_conf(class_conf);
2751    recvq = aclass->max_recvq;
2752    return recvq;
2753  }
2754
2755  /* XXX return a default?
2756   * if here, then there wasn't an attached conf with a recvq
2757   * that is very bad -Dianora
2758   */
2759  return DEFAULT_RECVQ;
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);
2772 <  struct ClassItem *class = NULL;
2773 <
2774 <  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)
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 <                           aconf->user, aconf->host);
1354 >                           "Warning *** Defaulting to default class for %s@%s",
1355 >                           conf->user, conf->host);
1356      else
1357        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1358 <                           "Warning *** Defaulting to default class for %s",
1359 <                           conf->name);
1358 >                           "Warning *** Defaulting to default class for %s",
1359 >                           conf->name);
1360    }
1361    else
1362 <    aconf->class_ptr = find_class(class_name);
2789 <
2790 <  if (aconf->class_ptr)
2791 <    class = map_to_conf(aconf->class_ptr);
1362 >    conf->class = class_find(class_name, 1);
1363  
1364 <  if (aconf->class_ptr == NULL || !class->active)
1364 >  if (conf->class == NULL)
1365    {
1366 <    if (conf->type == CLIENT_TYPE)
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 <                           aconf->user, aconf->host);
1368 >                           "Warning *** Defaulting to default class for %s@%s",
1369 >                           conf->user, conf->host);
1370      else
1371        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1372 <                           "Warning *** Defaulting to default class for %s",
1373 <                           conf->name);
1374 <    aconf->class_ptr = class_default;
2804 <  }
2805 < }
2806 <
2807 < /* conf_add_server()
2808 < *
2809 < * inputs       - pointer to config item
2810 < *              - pointer to link count already on this conf
2811 < * output       - NONE
2812 < * side effects - Add a connect block
2813 < */
2814 < int
2815 < conf_add_server(struct ConfItem *conf, const char *class_name)
2816 < {
2817 <  struct AccessItem *aconf = map_to_conf(conf);
2818 <
2819 <  conf_add_class_to_conf(conf, class_name);
2820 <
2821 <  if (!aconf->host || !conf->name)
2822 <  {
2823 <    sendto_realops_flags(UMODE_ALL, L_ALL,  SEND_NOTICE,
2824 <                         "Bad connect block");
2825 <    ilog(LOG_TYPE_IRCD, "Bad connect block");
2826 <    return -1;
2827 <  }
2828 <
2829 <  if (EmptyString(aconf->passwd))
2830 <  {
2831 <    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2832 <                         "Bad connect block, name %s",
2833 <                         conf->name);
2834 <    ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
2835 <    return -1;
1372 >                           "Warning *** Defaulting to default class for %s",
1373 >                           conf->name);
1374 >    conf->class = class_default;
1375    }
2837
2838  lookup_confhost(conf);
2839
2840  return 0;
1376   }
1377  
1378   /* yyerror()
# Line 2855 | Line 1390 | yyerror(const char *msg)
1390      return;
1391  
1392    strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1393 <  sendto_realops_flags(UMODE_ALL, L_ALL,  SEND_NOTICE,
1393 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1394 >                       "\"%s\", line %u: %s: %s",
1395 >                       conffilebuf, lineno + 1, msg, newlinebuf);
1396 >  ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1397 >       conffilebuf, lineno + 1, msg, newlinebuf);
1398 > }
1399 >
1400 > void
1401 > conf_error_report(const char *msg)
1402 > {
1403 >  char newlinebuf[IRCD_BUFSIZE];
1404 >
1405 >  strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1406 >  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1407                         "\"%s\", line %u: %s: %s",
1408                         conffilebuf, lineno + 1, msg, newlinebuf);
1409    ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
# Line 2864 | Line 1412 | yyerror(const char *msg)
1412  
1413   /*
1414   * valid_tkline()
1415 < *
1415 > *
1416   * inputs       - pointer to ascii string to check
1417   *              - whether the specified time is in seconds or minutes
1418   * output       - -1 not enough parameters
# Line 2873 | Line 1421 | yyerror(const char *msg)
1421   * Originally written by Dianora (Diane, db@db.net)
1422   */
1423   time_t
1424 < valid_tkline(const char *p, int minutes)
1424 > valid_tkline(const char *data, const int minutes)
1425   {
1426 +  const unsigned char *p = (const unsigned char *)data;
1427 +  unsigned char tmpch = '\0';
1428    time_t result = 0;
1429  
1430 <  for (; *p; ++p)
1430 >  while ((tmpch = *p++))
1431    {
1432 <    if (!IsDigit(*p))
1432 >    if (!IsDigit(tmpch))
1433        return 0;
1434  
1435      result *= 10;
1436 <    result += ((*p) & 0xF);
1436 >    result += (tmpch & 0xF);
1437    }
1438  
1439    /*
1440 <   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1440 >   * In the degenerate case where oper does a /quote kline 0 user@host :reason
1441     * i.e. they specifically use 0, I am going to return 1 instead
1442     * as a return value of non-zero is used to flag it as a temporary kline
1443     */
1444    if (result == 0)
1445      result = 1;
1446  
1447 <  /*
1447 >  /*
1448     * If the incoming time is in seconds convert it to minutes for the purpose
1449     * of this calculation
1450     */
1451    if (!minutes)
1452 <    result = result / (time_t)60;
1452 >    result = result / 60;
1453  
1454    if (result > MAX_TDKLINE_TIME)
1455      result = MAX_TDKLINE_TIME;
1456  
1457 <  result = result * (time_t)60;  /* turn it into seconds */
1457 >  result = result * 60;  /* turn it into seconds */
1458  
1459    return result;
1460   }
1461  
1462 + /* valid_wild_card_simple()
1463 + *
1464 + * inputs       - data to check for sufficient non-wildcard characters
1465 + * outputs      - 1 if valid, else 0
1466 + * side effects - none
1467 + */
1468 + int
1469 + valid_wild_card_simple(const char *data)
1470 + {
1471 +  const unsigned char *p = (const unsigned char *)data;
1472 +  unsigned char tmpch = '\0';
1473 +  unsigned int nonwild = 0;
1474 +
1475 +  while ((tmpch = *p++))
1476 +  {
1477 +    if (tmpch == '\\' && *p)
1478 +    {
1479 +      ++p;
1480 +      if (++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
1481 +        return 1;
1482 +    }
1483 +    else if (!IsMWildChar(tmpch))
1484 +    {
1485 +      if (++nonwild >= ConfigFileEntry.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 2920 | Line 1501 | valid_tkline(const char *p, int minutes)
1501   int
1502   valid_wild_card(struct Client *source_p, int warn, int count, ...)
1503   {
1504 <  char *p;
1505 <  char tmpch;
2925 <  int nonwild = 0;
1504 >  unsigned char tmpch = '\0';
1505 >  unsigned int nonwild = 0;
1506    va_list args;
1507  
1508    /*
# Line 2941 | 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 2954 | Line 1534 | valid_wild_card(struct Client *source_p,
1534           * break - no point in searching further.
1535           */
1536          if (++nonwild >= ConfigFileEntry.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 >                      ConfigFileEntry.min_nonwildcard);
1549 >  va_end(args);
1550    return 0;
1551   }
1552  
# Line 2975 | 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 2997 | Line 1582 | valid_wild_card(struct Client *source_p,
1582   */
1583   int
1584   parse_aline(const char *cmd, struct Client *source_p,
1585 <            int parc, char **parv,
1586 <            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1587 <            char **target_server, char **reason)
1585 >            int parc, char **parv,
1586 >            int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
1587 >            char **target_server, char **reason)
1588   {
1589    int found_tkline_time=0;
1590 <  static char def_reason[] = "No Reason";
1590 >  static char def_reason[] = CONF_NOREASON;
1591    static char user[USERLEN*4+1];
1592    static char host[HOSTLEN*4+1];
1593  
# Line 3020 | 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",
3024 <                 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),
3032 <               me.name, source_p->name, cmd);
1615 >    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1616      return -1;
1617    }
1618  
# Line 3043 | 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 3056 | 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);
3061 <        return -1;
1642 >        sendto_one_notice(source_p, &me, ":ON server not supported by %s", cmd);
1643 >        return -1;
1644        }
1645  
1646        if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
1647        {
1648 <        sendto_one(source_p, form_str(ERR_NOPRIVS),
3067 <                   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);
3075 <        return -1;
1654 >        sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, cmd);
1655 >        return -1;
1656        }
1657  
1658        *target_server = *parv;
# Line 3085 | 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 3093 | 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",
3097 <                 me.name, source_p->name);
1676 >      sendto_one_notice(source_p, &me, ":Invalid character '!' in kline");
1677        return -1;
1678      }
1679  
# Line 3111 | Line 1690 | parse_aline(const char *cmd, struct Clie
1690      {
1691        *reason = *parv;
1692        if (!valid_comment(source_p, *reason, 1))
1693 <        return -1;
1693 >        return -1;
1694      }
1695      else
1696        *reason = def_reason;
# Line 3150 | 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
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,
3182 <                   ":%s NOTICE %s :%s is E-lined",
3183 <                   me.name, source_p->name, target_p->name);
1761 >        sendto_one_notice(source_p, &me, ":%s is E-lined", target_p->name);
1762        return 0;
1763      }
1764  
# Line 3215 | Line 1793 | find_user_host(struct Client *source_p,
1793   int
1794   valid_comment(struct Client *source_p, char *comment, int warn)
1795   {
3218  if (strchr(comment, '"'))
3219  {
3220    if (warn)
3221      sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3222                 me.name, source_p->name);
3223    return 0;
3224  }
3225
1796    if (strlen(comment) > REASONLEN)
1797      comment[REASONLEN-1] = '\0';
1798  
# Line 3237 | Line 1807 | valid_comment(struct Client *source_p, c
1807   * side effects - none
1808   */
1809   int
1810 < match_conf_password(const char *password, const struct AccessItem *aconf)
1810 > match_conf_password(const char *password, const struct MaskItem *conf)
1811   {
1812    const char *encr = NULL;
1813  
1814 <  if (EmptyString(password) || EmptyString(aconf->passwd))
1814 >  if (EmptyString(password) || EmptyString(conf->passwd))
1815      return 0;
1816  
1817 <  if (aconf->flags & CONF_FLAGS_ENCRYPTED)
1818 <    encr = crypt(password, aconf->passwd);
1817 >  if (conf->flags & CONF_FLAGS_ENCRYPTED)
1818 >    encr = crypt(password, conf->passwd);
1819    else
1820      encr = password;
1821  
1822 <  return !strcmp(encr, aconf->passwd);
1822 >  return encr && !strcmp(encr, conf->passwd);
1823   }
1824  
1825   /*
# Line 3257 | Line 1827 | match_conf_password(const char *password
1827   *
1828   * inputs       - client sending the cluster
1829   *              - command name "KLINE" "XLINE" etc.
1830 < *              - capab -- CAP_KLN etc. from s_serv.h
1830 > *              - capab -- CAP_KLN etc. from server.h
1831   *              - cluster type -- CLUSTER_KLINE etc. from conf.h
1832   *              - pattern and args to send along
1833   * output       - none
# Line 3269 | Line 1839 | cluster_a_line(struct Client *source_p,
1839                 int capab, int cluster_type, const char *pattern, ...)
1840   {
1841    va_list args;
1842 <  char buffer[IRCD_BUFSIZE];
1842 >  char buffer[IRCD_BUFSIZE] = "";
1843    const dlink_node *ptr = NULL;
1844  
1845    va_start(args, pattern);
# Line 3278 | Line 1848 | cluster_a_line(struct Client *source_p,
1848  
1849    DLINK_FOREACH(ptr, cluster_items.head)
1850    {
1851 <    const struct ConfItem *conf = ptr->data;
1851 >    const struct MaskItem *conf = ptr->data;
1852  
1853      if (conf->flags & cluster_type)
1854        sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
1855 <                         "%s %s %s", command, conf->name, buffer);
1855 >                         "%s %s %s", command, conf->name, buffer);
1856    }
1857   }
1858  
# Line 3330 | Line 1900 | split_nuh(struct split_nuh_item *const i
1900    {
1901      *p = '\0';
1902  
1903 <    if (iptr->nickptr && *iptr->nuhmask != '\0')
1903 >    if (iptr->nickptr && *iptr->nuhmask)
1904        strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
1905  
1906 <    if ((q = strchr(++p, '@'))) {
1906 >    if ((q = strchr(++p, '@')))
1907 >    {
1908        *q++ = '\0';
1909  
1910 <      if (*p != '\0')
1910 >      if (*p)
1911          strlcpy(iptr->userptr, p, iptr->usersize);
1912  
1913 <      if (*q != '\0')
1913 >      if (*q)
1914          strlcpy(iptr->hostptr, q, iptr->hostsize);
1915      }
1916      else
1917      {
1918 <      if (*p != '\0')
1918 >      if (*p)
1919          strlcpy(iptr->userptr, p, iptr->usersize);
1920      }
1921    }
# Line 3356 | Line 1927 | split_nuh(struct split_nuh_item *const i
1927        /* if found a @ */
1928        *p++ = '\0';
1929  
1930 <      if (*iptr->nuhmask != '\0')
1930 >      if (*iptr->nuhmask)
1931          strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
1932  
1933 <      if (*p != '\0')
1933 >      if (*p)
1934          strlcpy(iptr->hostptr, p, iptr->hostsize);
1935      }
1936      else
# Line 3372 | Line 1943 | split_nuh(struct split_nuh_item *const i
1943      }
1944    }
1945   }
3375
3376 /*
3377 * flags_to_ascii
3378 *
3379 * inputs       - flags is a bitmask
3380 *              - pointer to table of ascii letters corresponding
3381 *                to each bit
3382 *              - flag 1 for convert ToLower if bit missing
3383 *                0 if ignore.
3384 * output       - none
3385 * side effects - string pointed to by p has bitmap chars written to it
3386 */
3387 static void
3388 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3389               int lowerit)
3390 {
3391  unsigned int mask = 1;
3392  int i = 0;
3393
3394  for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3395  {
3396    if (flags & mask)
3397      *p++ = bit_table[i];
3398    else if (lowerit)
3399      *p++ = ToLower(bit_table[i]);
3400  }
3401  *p = '\0';
3402 }
3403
3404 /*
3405 * cidr_limit_reached
3406 *
3407 * inputs       - int flag allowing over_rule of limits
3408 *              - pointer to the ip to be added
3409 *              - pointer to the class
3410 * output       - non zero if limit reached
3411 *                0 if limit not reached
3412 * side effects -
3413 */
3414 static int
3415 cidr_limit_reached(int over_rule,
3416                   struct irc_ssaddr *ip, struct ClassItem *aclass)
3417 {
3418  dlink_node *ptr = NULL;
3419  struct CidrItem *cidr;
3420
3421  if (aclass->number_per_cidr <= 0)
3422    return 0;
3423
3424  if (ip->ss.ss_family == AF_INET)
3425  {
3426    if (aclass->cidr_bitlen_ipv4 <= 0)
3427      return 0;
3428
3429    DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3430    {
3431      cidr = ptr->data;
3432      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3433      {
3434        if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3435          return -1;
3436        cidr->number_on_this_cidr++;
3437        return 0;
3438      }
3439    }
3440    cidr = MyMalloc(sizeof(struct CidrItem));
3441    cidr->number_on_this_cidr = 1;
3442    cidr->mask = *ip;
3443    mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv4);
3444    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3445  }
3446 #ifdef IPV6
3447  else if (aclass->cidr_bitlen_ipv6 > 0)
3448  {
3449    DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3450    {
3451      cidr = ptr->data;
3452      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3453      {
3454        if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3455          return -1;
3456        cidr->number_on_this_cidr++;
3457        return 0;
3458      }
3459    }
3460    cidr = MyMalloc(sizeof(struct CidrItem));
3461    cidr->number_on_this_cidr = 1;
3462    cidr->mask = *ip;
3463    mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv6);
3464    dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3465  }
3466 #endif
3467  return 0;
3468 }
3469
3470 /*
3471 * remove_from_cidr_check
3472 *
3473 * inputs       - pointer to the ip to be removed
3474 *              - pointer to the class
3475 * output       - NONE
3476 * side effects -
3477 */
3478 static void
3479 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3480 {
3481  dlink_node *ptr = NULL;
3482  dlink_node *next_ptr = NULL;
3483  struct CidrItem *cidr;
3484
3485  if (aclass->number_per_cidr == 0)
3486    return;
3487
3488  if (ip->ss.ss_family == AF_INET)
3489  {
3490    if (aclass->cidr_bitlen_ipv4 <= 0)
3491      return;
3492
3493    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3494    {
3495      cidr = ptr->data;
3496      if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3497      {
3498        cidr->number_on_this_cidr--;
3499        if (cidr->number_on_this_cidr == 0)
3500        {
3501          dlinkDelete(ptr, &aclass->list_ipv4);
3502          MyFree(cidr);
3503          return;
3504        }
3505      }
3506    }
3507  }
3508 #ifdef IPV6
3509  else if (aclass->cidr_bitlen_ipv6 > 0)
3510  {
3511    DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3512    {
3513      cidr = ptr->data;
3514      if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3515      {
3516        cidr->number_on_this_cidr--;
3517        if (cidr->number_on_this_cidr == 0)
3518        {
3519          dlinkDelete(ptr, &aclass->list_ipv6);
3520          MyFree(cidr);
3521          return;
3522        }
3523      }
3524    }
3525  }
3526 #endif
3527 }
3528
3529 static void
3530 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3531                  dlink_list *old_list, dlink_list *new_list, int changed)
3532 {
3533  dlink_node *ptr;
3534  struct Client *client_p;
3535  struct ConfItem *conf;
3536  struct AccessItem *aconf;
3537
3538  if (!changed)
3539  {
3540    *new_list = *old_list;
3541    old_list->head = old_list->tail = NULL;
3542    old_list->length = 0;
3543    return;
3544  }
3545
3546  DLINK_FOREACH(ptr, local_client_list.head)
3547  {
3548    client_p = ptr->data;
3549    if (client_p->localClient->aftype != aftype)
3550      continue;
3551    if (dlink_list_length(&client_p->localClient->confs) == 0)
3552      continue;
3553
3554    conf = client_p->localClient->confs.tail->data;
3555    if (conf->type == CLIENT_TYPE)
3556    {
3557      aconf = map_to_conf(conf);
3558      if (aconf->class_ptr == oldcl)
3559        cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3560    }
3561  }
3562 }
3563
3564 /*
3565 * rebuild_cidr_class
3566 *
3567 * inputs       - pointer to old conf
3568 *              - pointer to new_class
3569 * output       - none
3570 * side effects - rebuilds the class link list of cidr blocks
3571 */
3572 void
3573 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3574 {
3575  struct ClassItem *old_class = map_to_conf(conf);
3576
3577  if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
3578  {
3579    if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
3580      rebuild_cidr_list(AF_INET, conf, new_class,
3581                        &old_class->list_ipv4, &new_class->list_ipv4,
3582                        old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
3583
3584 #ifdef IPV6
3585    if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
3586      rebuild_cidr_list(AF_INET6, conf, new_class,
3587                        &old_class->list_ipv6, &new_class->list_ipv6,
3588                        old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
3589 #endif
3590  }
3591
3592  destroy_cidr_class(old_class);
3593 }
3594
3595 /*
3596 * destroy_cidr_list
3597 *
3598 * inputs       - pointer to class dlink list of cidr blocks
3599 * output       - none
3600 * side effects - completely destroys the class link list of cidr blocks
3601 */
3602 static void
3603 destroy_cidr_list(dlink_list *list)
3604 {
3605  dlink_node *ptr = NULL, *next_ptr = NULL;
3606
3607  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3608  {
3609    dlinkDelete(ptr, list);
3610    MyFree(ptr->data);
3611  }
3612 }
3613
3614 /*
3615 * destroy_cidr_class
3616 *
3617 * inputs       - pointer to class
3618 * output       - none
3619 * side effects - completely destroys the class link list of cidr blocks
3620 */
3621 static void
3622 destroy_cidr_class(struct ClassItem *aclass)
3623 {
3624  destroy_cidr_list(&aclass->list_ipv4);
3625  destroy_cidr_list(&aclass->list_ipv6);
3626 }

Diff Legend

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