ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1622
Committed: Thu Nov 1 13:16:37 2012 UTC (12 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 89516 byte(s)
Log Message:
- klines, dlines, xlines, glines and resv now make use of the new database;
  also, temporary *lines are now stored, so they're not lost after
  restarting the ircd. This also applies to G-lines.

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 michael 1309 * conf.c: Configuration file functions.
4 adx 30 *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26 michael 1011 #include "list.h"
27 adx 30 #include "ircd_defs.h"
28 michael 1011 #include "balloc.h"
29 michael 1309 #include "conf.h"
30 adx 30 #include "s_serv.h"
31     #include "resv.h"
32     #include "channel.h"
33     #include "client.h"
34     #include "event.h"
35     #include "hook.h"
36     #include "irc_string.h"
37     #include "s_bsd.h"
38     #include "ircd.h"
39     #include "listener.h"
40     #include "hostmask.h"
41     #include "modules.h"
42     #include "numeric.h"
43     #include "fdlist.h"
44 michael 1309 #include "log.h"
45 adx 30 #include "send.h"
46     #include "s_gline.h"
47     #include "memory.h"
48     #include "irc_res.h"
49     #include "userhost.h"
50     #include "s_user.h"
51     #include "channel_mode.h"
52 michael 1243 #include "parse.h"
53     #include "s_misc.h"
54 michael 1622 #include "conf_db.h"
55 adx 30
56     struct Callback *client_check_cb = NULL;
57     struct config_server_hide ConfigServerHide;
58    
59     /* general conf items link list root, other than k lines etc. */
60 michael 1157 dlink_list service_items = { NULL, NULL, 0 };
61 adx 30 dlink_list server_items = { NULL, NULL, 0 };
62     dlink_list cluster_items = { NULL, NULL, 0 };
63     dlink_list oconf_items = { NULL, NULL, 0 };
64     dlink_list uconf_items = { NULL, NULL, 0 };
65     dlink_list xconf_items = { NULL, NULL, 0 };
66     dlink_list rxconf_items = { NULL, NULL, 0 };
67     dlink_list rkconf_items = { NULL, NULL, 0 };
68     dlink_list nresv_items = { NULL, NULL, 0 };
69     dlink_list class_items = { NULL, NULL, 0 };
70    
71     dlink_list temporary_xlines = { NULL, NULL, 0 };
72     dlink_list temporary_resv = { NULL, NULL, 0 };
73    
74     extern unsigned int lineno;
75     extern char linebuf[];
76     extern char conffilebuf[IRCD_BUFSIZE];
77     extern int yyparse(); /* defined in y.tab.c */
78    
79 michael 967 struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
80    
81 adx 30 /* internally defined functions */
82 michael 1325 static void read_conf(FILE *);
83 adx 30 static void clear_out_old_conf(void);
84     static void flush_deleted_I_P(void);
85     static void expire_tklines(dlink_list *);
86     static void garbage_collect_ip_entries(void);
87     static int hash_ip(struct irc_ssaddr *);
88     static int verify_access(struct Client *, const char *);
89     static int attach_iline(struct Client *, struct ConfItem *);
90     static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
91     static dlink_list *map_to_list(ConfType);
92     static struct AccessItem *find_regexp_kline(const char *[]);
93     static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
94    
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 michael 1013 void *
127 adx 30 map_to_conf(struct ConfItem *aconf)
128     {
129     void *conf;
130 michael 1013 conf = (void *)((uintptr_t)aconf +
131     (uintptr_t)sizeof(struct ConfItem));
132 adx 30 return(conf);
133     }
134    
135 michael 1013 struct ConfItem *
136 adx 30 unmap_conf_item(void *aconf)
137     {
138     struct ConfItem *conf;
139    
140 michael 1013 conf = (struct ConfItem *)((uintptr_t)aconf -
141     (uintptr_t)sizeof(struct ConfItem));
142 adx 30 return(conf);
143     }
144    
145     /* conf_dns_callback()
146     *
147     * inputs - pointer to struct AccessItem
148     * - pointer to DNSReply reply
149     * output - none
150     * side effects - called when resolver query finishes
151     * if the query resulted in a successful search, hp will contain
152     * a non-null pointer, otherwise hp will be null.
153     * if successful save hp in the conf item it was called with
154     */
155     static void
156 michael 992 conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
157 adx 30 {
158 michael 1005 struct AccessItem *aconf = vptr;
159 adx 30
160 michael 992 aconf->dns_pending = 0;
161 adx 30
162 michael 992 if (addr != NULL)
163 michael 1389 memcpy(&aconf->addr, addr, sizeof(aconf->addr));
164 michael 992 else
165     aconf->dns_failed = 1;
166 adx 30 }
167    
168     /* conf_dns_lookup()
169     *
170     * do a nameserver lookup of the conf host
171     * if the conf entry is currently doing a ns lookup do nothing, otherwise
172     * allocate a dns_query and start ns lookup.
173     */
174     static void
175     conf_dns_lookup(struct AccessItem *aconf)
176     {
177 michael 992 if (!aconf->dns_pending)
178 adx 30 {
179 michael 992 aconf->dns_pending = 1;
180     gethost_byname(conf_dns_callback, aconf, aconf->host);
181 adx 30 }
182     }
183    
184     /* make_conf_item()
185     *
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)
192     {
193     struct ConfItem *conf = NULL;
194     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;
222    
223     case KLINE_TYPE:
224     status = CONF_KLINE;
225     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 michael 1009 #ifdef HAVE_LIBPCRE
263 adx 30 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 michael 1009 #endif
277 adx 30 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 michael 1157 case SERVICE_TYPE:
294     status = CONF_SERVICE;
295     conf = MyMalloc(sizeof(struct ConfItem));
296     dlinkAdd(conf, &conf->node, &service_items);
297     break;
298    
299 adx 30 case CLASS_TYPE:
300 michael 671 conf = MyMalloc(sizeof(struct ConfItem) +
301     sizeof(struct ClassItem));
302 adx 30 dlinkAdd(conf, &conf->node, &class_items);
303 michael 671
304     aclass = map_to_conf(conf);
305     aclass->active = 1;
306 michael 1377 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 michael 1516 aclass->max_recvq = DEFAULT_RECVQ;
311 michael 671
312 adx 30 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;
321    
322 michael 671 return conf;
323 adx 30 }
324    
325     void
326     delete_conf_item(struct ConfItem *conf)
327     {
328 michael 1383 dlink_node *m = NULL, *m_next = NULL;
329 adx 30 struct MatchItem *match_item;
330     struct AccessItem *aconf;
331     ConfType type = conf->type;
332    
333     MyFree(conf->name);
334     conf->name = NULL;
335    
336     switch(type)
337     {
338     case DLINE_TYPE:
339     case EXEMPTDLINE_TYPE:
340     case GLINE_TYPE:
341     case KLINE_TYPE:
342     case CLIENT_TYPE:
343     case OPER_TYPE:
344     case SERVER_TYPE:
345     aconf = map_to_conf(conf);
346    
347 michael 992 if (aconf->dns_pending)
348     delete_resolver_queries(aconf);
349 adx 30 if (aconf->passwd != NULL)
350     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->user);
359     MyFree(aconf->host);
360 michael 1411 #ifdef HAVE_LIBCRYPTO
361 michael 1306 MyFree(aconf->cipher_list);
362 michael 1411
363 adx 30 if (aconf->rsa_public_key)
364     RSA_free(aconf->rsa_public_key);
365     MyFree(aconf->rsa_public_key_file);
366     #endif
367    
368     /* Yes, sigh. switch on type again */
369     switch(type)
370     {
371     case EXEMPTDLINE_TYPE:
372     case DLINE_TYPE:
373     case GLINE_TYPE:
374     case KLINE_TYPE:
375     case CLIENT_TYPE:
376     MyFree(conf);
377     break;
378    
379     case OPER_TYPE:
380     aconf = map_to_conf(conf);
381     if (!IsConfIllegal(aconf))
382     dlinkDelete(&conf->node, &oconf_items);
383     MyFree(conf);
384     break;
385    
386     case SERVER_TYPE:
387     aconf = map_to_conf(conf);
388 michael 1383
389     DLINK_FOREACH_SAFE(m, m_next, aconf->hub_list.head)
390     {
391     MyFree(m->data);
392     free_dlink_node(m);
393     }
394    
395     DLINK_FOREACH_SAFE(m, m_next, aconf->leaf_list.head)
396     {
397     MyFree(m->data);
398     free_dlink_node(m);
399     }
400    
401 adx 30 if (!IsConfIllegal(aconf))
402     dlinkDelete(&conf->node, &server_items);
403     MyFree(conf);
404     break;
405    
406     default:
407     break;
408     }
409     break;
410    
411     case ULINE_TYPE:
412     match_item = map_to_conf(conf);
413     MyFree(match_item->user);
414     MyFree(match_item->host);
415     MyFree(match_item->reason);
416     dlinkDelete(&conf->node, &uconf_items);
417     MyFree(conf);
418     break;
419    
420     case XLINE_TYPE:
421     match_item = map_to_conf(conf);
422     MyFree(match_item->user);
423     MyFree(match_item->host);
424     MyFree(match_item->reason);
425     dlinkDelete(&conf->node, &xconf_items);
426     MyFree(conf);
427     break;
428 michael 1009 #ifdef HAVE_LIBPCRE
429 adx 30 case RKLINE_TYPE:
430     aconf = map_to_conf(conf);
431     MyFree(aconf->regexuser);
432     MyFree(aconf->regexhost);
433     MyFree(aconf->user);
434     MyFree(aconf->host);
435     MyFree(aconf->reason);
436     dlinkDelete(&conf->node, &rkconf_items);
437     MyFree(conf);
438     break;
439    
440     case RXLINE_TYPE:
441     MyFree(conf->regexpname);
442     match_item = map_to_conf(conf);
443     MyFree(match_item->user);
444     MyFree(match_item->host);
445     MyFree(match_item->reason);
446     dlinkDelete(&conf->node, &rxconf_items);
447     MyFree(conf);
448     break;
449 michael 1009 #endif
450 adx 30 case NRESV_TYPE:
451     match_item = map_to_conf(conf);
452     MyFree(match_item->user);
453     MyFree(match_item->host);
454     MyFree(match_item->reason);
455     dlinkDelete(&conf->node, &nresv_items);
456 michael 433
457     if (conf->flags & CONF_FLAGS_TEMPORARY)
458     if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
459     free_dlink_node(m);
460    
461 adx 30 MyFree(conf);
462     break;
463    
464     case CLUSTER_TYPE:
465     dlinkDelete(&conf->node, &cluster_items);
466     MyFree(conf);
467     break;
468    
469     case CRESV_TYPE:
470 michael 433 if (conf->flags & CONF_FLAGS_TEMPORARY)
471     if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
472     free_dlink_node(m);
473    
474 adx 30 MyFree(conf);
475     break;
476    
477     case CLASS_TYPE:
478     dlinkDelete(&conf->node, &class_items);
479     MyFree(conf);
480     break;
481    
482 michael 1157 case SERVICE_TYPE:
483     dlinkDelete(&conf->node, &service_items);
484     MyFree(conf);
485     break;
486    
487 adx 30 default:
488     break;
489     }
490     }
491    
492     /* free_access_item()
493     *
494     * inputs - pointer to conf to free
495     * output - none
496     * side effects - crucial password fields are zeroed, conf is freed
497     */
498     void
499     free_access_item(struct AccessItem *aconf)
500     {
501     struct ConfItem *conf;
502    
503     if (aconf == NULL)
504     return;
505     conf = unmap_conf_item(aconf);
506     delete_conf_item(conf);
507     }
508    
509     static const unsigned int shared_bit_table[] =
510     { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
511    
512     /* report_confitem_types()
513     *
514     * inputs - pointer to client requesting confitem report
515     * - ConfType to report
516     * output - none
517     * side effects -
518     */
519     void
520 michael 1368 report_confitem_types(struct Client *source_p, ConfType type)
521 adx 30 {
522 michael 1383 dlink_node *ptr = NULL, *dptr = NULL;
523 adx 30 struct ConfItem *conf = NULL;
524     struct AccessItem *aconf = NULL;
525     struct MatchItem *matchitem = NULL;
526     struct ClassItem *classitem = NULL;
527     char buf[12];
528     char *p = NULL;
529    
530     switch (type)
531     {
532     case XLINE_TYPE:
533     DLINK_FOREACH(ptr, xconf_items.head)
534     {
535     conf = ptr->data;
536     matchitem = map_to_conf(conf);
537    
538     sendto_one(source_p, form_str(RPL_STATSXLINE),
539     me.name, source_p->name,
540     matchitem->hold ? "x": "X", matchitem->count,
541     conf->name, matchitem->reason);
542     }
543     break;
544    
545 michael 1009 #ifdef HAVE_LIBPCRE
546 adx 30 case RXLINE_TYPE:
547     DLINK_FOREACH(ptr, rxconf_items.head)
548     {
549     conf = ptr->data;
550     matchitem = map_to_conf(conf);
551    
552     sendto_one(source_p, form_str(RPL_STATSXLINE),
553     me.name, source_p->name,
554 michael 1368 "XR", matchitem->count,
555 adx 30 conf->name, matchitem->reason);
556     }
557     break;
558    
559     case RKLINE_TYPE:
560     DLINK_FOREACH(ptr, rkconf_items.head)
561     {
562     aconf = map_to_conf((conf = ptr->data));
563    
564     sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
565 michael 1368 source_p->name, "KR", aconf->host, aconf->user,
566 michael 1622 aconf->reason);
567 adx 30 }
568     break;
569 michael 1009 #endif
570 adx 30
571     case ULINE_TYPE:
572     DLINK_FOREACH(ptr, uconf_items.head)
573     {
574     conf = ptr->data;
575     matchitem = map_to_conf(conf);
576    
577     p = buf;
578    
579     /* some of these are redundant for the sake of
580     * consistency with cluster{} flags
581     */
582     *p++ = 'c';
583     flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
584    
585     sendto_one(source_p, form_str(RPL_STATSULINE),
586     me.name, source_p->name, conf->name,
587     matchitem->user?matchitem->user: "*",
588     matchitem->host?matchitem->host: "*", buf);
589     }
590    
591     DLINK_FOREACH(ptr, cluster_items.head)
592     {
593     conf = ptr->data;
594    
595     p = buf;
596    
597     *p++ = 'C';
598     flags_to_ascii(conf->flags, shared_bit_table, p, 0);
599    
600     sendto_one(source_p, form_str(RPL_STATSULINE),
601     me.name, source_p->name, conf->name,
602     "*", "*", buf);
603     }
604    
605     break;
606    
607     case OPER_TYPE:
608     DLINK_FOREACH(ptr, oconf_items.head)
609     {
610     conf = ptr->data;
611     aconf = map_to_conf(conf);
612    
613     /* Don't allow non opers to see oper privs */
614 michael 1219 if (HasUMode(source_p, UMODE_OPER))
615 adx 30 sendto_one(source_p, form_str(RPL_STATSOLINE),
616     me.name, source_p->name, 'O', aconf->user, aconf->host,
617     conf->name, oper_privs_as_string(aconf->port),
618     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
619     else
620     sendto_one(source_p, form_str(RPL_STATSOLINE),
621     me.name, source_p->name, 'O', aconf->user, aconf->host,
622     conf->name, "0",
623     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
624     }
625     break;
626    
627     case CLASS_TYPE:
628     DLINK_FOREACH(ptr, class_items.head)
629     {
630     conf = ptr->data;
631     classitem = map_to_conf(conf);
632     sendto_one(source_p, form_str(RPL_STATSYLINE),
633     me.name, source_p->name, 'Y',
634 michael 1377 conf->name, classitem->ping_freq,
635     classitem->con_freq,
636     classitem->max_total, classitem->max_sendq,
637 michael 1516 classitem->max_recvq,
638 michael 1377 classitem->curr_user_count,
639 michael 1417 classitem->number_per_cidr, classitem->cidr_bitlen_ipv4,
640     classitem->number_per_cidr, classitem->cidr_bitlen_ipv6,
641 michael 671 classitem->active ? "active" : "disabled");
642 adx 30 }
643     break;
644    
645     case CONF_TYPE:
646     case CLIENT_TYPE:
647     break;
648    
649 michael 1175 case SERVICE_TYPE:
650 michael 1157 DLINK_FOREACH(ptr, service_items.head)
651     {
652     conf = ptr->data;
653 michael 1175 sendto_one(source_p, form_str(RPL_STATSSERVICE),
654     me.name, source_p->name, 'S', "*", conf->name, 0, 0);
655 michael 1157 }
656     break;
657    
658 adx 30 case SERVER_TYPE:
659     DLINK_FOREACH(ptr, server_items.head)
660     {
661     p = buf;
662    
663     conf = ptr->data;
664     aconf = map_to_conf(conf);
665    
666     buf[0] = '\0';
667    
668     if (IsConfAllowAutoConn(aconf))
669     *p++ = 'A';
670 michael 1303 if (IsConfSSL(aconf))
671     *p++ = 'S';
672 adx 30 if (buf[0] == '\0')
673     *p++ = '*';
674    
675     *p = '\0';
676    
677 michael 671 /*
678     * Allow admins to see actual ips unless hide_server_ips is enabled
679 adx 30 */
680 michael 1219 if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
681 adx 30 sendto_one(source_p, form_str(RPL_STATSCLINE),
682     me.name, source_p->name, 'C', aconf->host,
683     buf, conf->name, aconf->port,
684     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
685     else
686     sendto_one(source_p, form_str(RPL_STATSCLINE),
687     me.name, source_p->name, 'C',
688     "*@127.0.0.1", buf, conf->name, aconf->port,
689     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
690     }
691     break;
692    
693     case HUB_TYPE:
694 michael 1383 DLINK_FOREACH(ptr, server_items.head)
695 adx 30 {
696     conf = ptr->data;
697 michael 1383 aconf = map_to_conf(conf);
698    
699     DLINK_FOREACH(dptr, aconf->hub_list.head)
700     sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
701     source_p->name, 'H', dptr->data, conf->name, 0, "*");
702 adx 30 }
703     break;
704    
705     case LEAF_TYPE:
706 michael 1383 DLINK_FOREACH(ptr, server_items.head)
707 adx 30 {
708     conf = ptr->data;
709 michael 1383 aconf = map_to_conf(conf);
710    
711     DLINK_FOREACH(dptr, aconf->leaf_list.head)
712     sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
713     source_p->name, 'L', dptr->data, conf->name, 0, "*");
714 adx 30 }
715     break;
716    
717     case GLINE_TYPE:
718     case KLINE_TYPE:
719     case DLINE_TYPE:
720     case EXEMPTDLINE_TYPE:
721     case CRESV_TYPE:
722     case NRESV_TYPE:
723     case CLUSTER_TYPE:
724 michael 1009 default:
725 adx 30 break;
726     }
727     }
728    
729     /* check_client()
730     *
731     * inputs - pointer to client
732     * output - 0 = Success
733     * NOT_AUTHORIZED (-1) = Access denied (no I line match)
734     * IRCD_SOCKET_ERROR (-2) = Bad socket.
735     * I_LINE_FULL (-3) = I-line is full
736     * TOO_MANY (-4) = Too many connections from hostname
737     * BANNED_CLIENT (-5) = K-lined
738     * side effects - Ordinary client access check.
739     * Look for conf lines which have the same
740     * status as the flags passed.
741     */
742     static void *
743     check_client(va_list args)
744     {
745     struct Client *source_p = va_arg(args, struct Client *);
746     const char *username = va_arg(args, const char *);
747     int i;
748    
749     /* I'm already in big trouble if source_p->localClient is NULL -db */
750     if ((i = verify_access(source_p, username)))
751 michael 1247 ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
752 adx 30 source_p->name, source_p->sockhost);
753    
754     switch (i)
755     {
756     case TOO_MANY:
757 michael 1618 sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
758 adx 30 "Too many on IP for %s (%s).",
759     get_client_name(source_p, SHOW_IP),
760     source_p->sockhost);
761 michael 1247 ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
762 adx 30 get_client_name(source_p, SHOW_IP));
763 michael 896 ++ServerStats.is_ref;
764 adx 30 exit_client(source_p, &me, "No more connections allowed on that IP");
765     break;
766    
767     case I_LINE_FULL:
768 michael 1618 sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
769     "auth{} block is full for %s (%s).",
770 adx 30 get_client_name(source_p, SHOW_IP),
771     source_p->sockhost);
772 michael 1247 ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
773 adx 30 get_client_name(source_p, SHOW_IP));
774 michael 896 ++ServerStats.is_ref;
775 adx 30 exit_client(source_p, &me,
776     "No more connections allowed in your connection class");
777     break;
778    
779     case NOT_AUTHORIZED:
780 michael 896 ++ServerStats.is_ref;
781 adx 30 /* jdc - lists server name & port connections are on */
782     /* a purely cosmetical change */
783 michael 1618 sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
784 adx 30 "Unauthorized client connection from %s [%s] on [%s/%u].",
785     get_client_name(source_p, SHOW_IP),
786 michael 891 source_p->sockhost,
787 adx 30 source_p->localClient->listener->name,
788     source_p->localClient->listener->port);
789 michael 1247 ilog(LOG_TYPE_IRCD,
790 adx 30 "Unauthorized client connection from %s on [%s/%u].",
791     get_client_name(source_p, SHOW_IP),
792     source_p->localClient->listener->name,
793     source_p->localClient->listener->port);
794    
795 michael 1549 exit_client(source_p, &me, "You are not authorized to use this server");
796 adx 30 break;
797 michael 891
798 adx 30 case BANNED_CLIENT:
799 michael 1549 exit_client(source_p, &me, "Banned");
800 michael 896 ++ServerStats.is_ref;
801 adx 30 break;
802    
803     case 0:
804     default:
805     break;
806     }
807    
808     return (i < 0 ? NULL : source_p);
809     }
810    
811     /* verify_access()
812     *
813     * inputs - pointer to client to verify
814     * - pointer to proposed username
815     * output - 0 if success -'ve if not
816     * side effect - find the first (best) I line to attach.
817     */
818     static int
819     verify_access(struct Client *client_p, const char *username)
820     {
821     struct AccessItem *aconf = NULL, *rkconf = NULL;
822     struct ConfItem *conf = NULL;
823     char non_ident[USERLEN + 1] = { '~', '\0' };
824     const char *uhi[3];
825    
826     if (IsGotId(client_p))
827     {
828     aconf = find_address_conf(client_p->host, client_p->username,
829     &client_p->localClient->ip,
830     client_p->localClient->aftype,
831     client_p->localClient->passwd);
832     }
833     else
834     {
835     strlcpy(non_ident+1, username, sizeof(non_ident)-1);
836     aconf = find_address_conf(client_p->host,non_ident,
837     &client_p->localClient->ip,
838     client_p->localClient->aftype,
839     client_p->localClient->passwd);
840     }
841    
842     uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
843     uhi[1] = client_p->host;
844     uhi[2] = client_p->sockhost;
845    
846     rkconf = find_regexp_kline(uhi);
847    
848     if (aconf != NULL)
849     {
850     if (IsConfClient(aconf) && !rkconf)
851     {
852     conf = unmap_conf_item(aconf);
853    
854     if (IsConfRedir(aconf))
855     {
856     sendto_one(client_p, form_str(RPL_REDIR),
857     me.name, client_p->name,
858     conf->name ? conf->name : "",
859     aconf->port);
860     return(NOT_AUTHORIZED);
861     }
862    
863     if (IsConfDoIdentd(aconf))
864     SetNeedId(client_p);
865    
866     /* Thanks for spoof idea amm */
867     if (IsConfDoSpoofIp(aconf))
868     {
869     conf = unmap_conf_item(aconf);
870    
871     if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
872 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
873     "%s spoofing: %s as %s",
874 adx 30 client_p->name, client_p->host, conf->name);
875     strlcpy(client_p->host, conf->name, sizeof(client_p->host));
876     SetIPSpoof(client_p);
877     }
878    
879     return(attach_iline(client_p, conf));
880     }
881     else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
882     {
883     /* XXX */
884     aconf = rkconf ? rkconf : aconf;
885     if (IsConfGline(aconf))
886     sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
887     client_p->name);
888 michael 1549 sendto_one(client_p, ":%s NOTICE %s :*** Banned: %s",
889     me.name, client_p->name, aconf->reason);
890 adx 30 return(BANNED_CLIENT);
891     }
892     }
893    
894     return(NOT_AUTHORIZED);
895     }
896    
897     /* attach_iline()
898     *
899     * inputs - client pointer
900     * - conf pointer
901     * output -
902     * side effects - do actual attach
903     */
904     static int
905     attach_iline(struct Client *client_p, struct ConfItem *conf)
906     {
907     struct AccessItem *aconf;
908     struct ClassItem *aclass;
909     struct ip_entry *ip_found;
910     int a_limit_reached = 0;
911     int local = 0, global = 0, ident = 0;
912    
913     ip_found = find_or_add_ip(&client_p->localClient->ip);
914     ip_found->count++;
915     SetIpHash(client_p);
916    
917 michael 624 aconf = map_to_conf(conf);
918 adx 30 if (aconf->class_ptr == NULL)
919     return NOT_AUTHORIZED; /* If class is missing, this is best */
920    
921 michael 624 aclass = map_to_conf(aconf->class_ptr);
922 adx 30
923     count_user_host(client_p->username, client_p->host,
924     &global, &local, &ident);
925    
926     /* XXX blah. go down checking the various silly limits
927     * setting a_limit_reached if any limit is reached.
928     * - Dianora
929     */
930 michael 1377 if (aclass->max_total != 0 && aclass->curr_user_count >= aclass->max_total)
931 adx 30 a_limit_reached = 1;
932 michael 1377 else if (aclass->max_perip != 0 && ip_found->count > aclass->max_perip)
933 adx 30 a_limit_reached = 1;
934 michael 1377 else if (aclass->max_local != 0 && local >= aclass->max_local)
935 adx 30 a_limit_reached = 1;
936 michael 1377 else if (aclass->max_global != 0 && global >= aclass->max_global)
937 adx 30 a_limit_reached = 1;
938 michael 1377 else if (aclass->max_ident != 0 && ident >= aclass->max_ident &&
939 adx 30 client_p->username[0] != '~')
940     a_limit_reached = 1;
941    
942     if (a_limit_reached)
943     {
944     if (!IsConfExemptLimits(aconf))
945 michael 624 return TOO_MANY; /* Already at maximum allowed */
946 adx 30
947     sendto_one(client_p,
948     ":%s NOTICE %s :*** Your connection class is full, "
949     "but you have exceed_limit = yes;", me.name, client_p->name);
950     }
951    
952     return attach_conf(client_p, conf);
953     }
954    
955     /* init_ip_hash_table()
956     *
957     * inputs - NONE
958     * output - NONE
959     * side effects - allocate memory for ip_entry(s)
960     * - clear the ip hash table
961     */
962     void
963     init_ip_hash_table(void)
964     {
965     ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
966     2 * hard_fdlimit);
967     memset(ip_hash_table, 0, sizeof(ip_hash_table));
968     }
969    
970     /* find_or_add_ip()
971     *
972     * inputs - pointer to struct irc_ssaddr
973     * output - pointer to a struct ip_entry
974     * side effects -
975     *
976     * If the ip # was not found, a new struct ip_entry is created, and the ip
977     * count set to 0.
978     */
979     static struct ip_entry *
980     find_or_add_ip(struct irc_ssaddr *ip_in)
981     {
982     struct ip_entry *ptr, *newptr;
983     int hash_index = hash_ip(ip_in), res;
984     struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
985     #ifdef IPV6
986     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
987     #endif
988    
989     for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
990     {
991     #ifdef IPV6
992     if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
993     continue;
994     if (ip_in->ss.ss_family == AF_INET6)
995     {
996     ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
997     res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
998     }
999     else
1000     #endif
1001     {
1002     ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1003     res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1004     }
1005     if (res == 0)
1006     {
1007     /* Found entry already in hash, return it. */
1008     return ptr;
1009     }
1010     }
1011    
1012     if (ip_entries_count >= 2 * hard_fdlimit)
1013     garbage_collect_ip_entries();
1014    
1015     newptr = BlockHeapAlloc(ip_entry_heap);
1016     ip_entries_count++;
1017     memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
1018    
1019     newptr->next = ip_hash_table[hash_index];
1020     ip_hash_table[hash_index] = newptr;
1021    
1022     return newptr;
1023     }
1024    
1025     /* remove_one_ip()
1026     *
1027     * inputs - unsigned long IP address value
1028     * output - NONE
1029     * side effects - The ip address given, is looked up in ip hash table
1030     * and number of ip#'s for that ip decremented.
1031     * If ip # count reaches 0 and has expired,
1032     * the struct ip_entry is returned to the ip_entry_heap
1033     */
1034     void
1035     remove_one_ip(struct irc_ssaddr *ip_in)
1036     {
1037     struct ip_entry *ptr;
1038     struct ip_entry *last_ptr = NULL;
1039     int hash_index = hash_ip(ip_in), res;
1040     struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1041     #ifdef IPV6
1042     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1043     #endif
1044    
1045     for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1046     {
1047     #ifdef IPV6
1048     if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1049     continue;
1050     if (ip_in->ss.ss_family == AF_INET6)
1051     {
1052     ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1053     res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1054     }
1055     else
1056     #endif
1057     {
1058     ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1059     res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1060     }
1061     if (res)
1062     continue;
1063     if (ptr->count > 0)
1064     ptr->count--;
1065     if (ptr->count == 0 &&
1066     (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1067     {
1068     if (last_ptr != NULL)
1069     last_ptr->next = ptr->next;
1070     else
1071     ip_hash_table[hash_index] = ptr->next;
1072    
1073     BlockHeapFree(ip_entry_heap, ptr);
1074     ip_entries_count--;
1075     return;
1076     }
1077     last_ptr = ptr;
1078     }
1079     }
1080    
1081     /* hash_ip()
1082     *
1083     * input - pointer to an irc_inaddr
1084     * output - integer value used as index into hash table
1085     * side effects - hopefully, none
1086     */
1087     static int
1088     hash_ip(struct irc_ssaddr *addr)
1089     {
1090     if (addr->ss.ss_family == AF_INET)
1091     {
1092     struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
1093     int hash;
1094 michael 1032 uint32_t ip;
1095 adx 30
1096     ip = ntohl(v4->sin_addr.s_addr);
1097     hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
1098     return hash;
1099     }
1100     #ifdef IPV6
1101     else
1102     {
1103     int hash;
1104     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
1105 michael 1032 uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
1106 adx 30
1107     hash = ip[0] ^ ip[3];
1108     hash ^= hash >> 16;
1109     hash ^= hash >> 8;
1110     hash = hash & (IP_HASH_SIZE - 1);
1111     return hash;
1112     }
1113     #else
1114     return 0;
1115     #endif
1116     }
1117    
1118     /* count_ip_hash()
1119     *
1120     * inputs - pointer to counter of number of ips hashed
1121     * - pointer to memory used for ip hash
1122     * output - returned via pointers input
1123     * side effects - NONE
1124     *
1125     * number of hashed ip #'s is counted up, plus the amount of memory
1126     * used in the hash.
1127     */
1128     void
1129 michael 948 count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
1130 adx 30 {
1131     struct ip_entry *ptr;
1132     int i;
1133    
1134     *number_ips_stored = 0;
1135     *mem_ips_stored = 0;
1136    
1137     for (i = 0; i < IP_HASH_SIZE; i++)
1138     {
1139     for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
1140     {
1141     *number_ips_stored += 1;
1142     *mem_ips_stored += sizeof(struct ip_entry);
1143     }
1144     }
1145     }
1146    
1147     /* garbage_collect_ip_entries()
1148     *
1149     * input - NONE
1150     * output - NONE
1151     * side effects - free up all ip entries with no connections
1152     */
1153     static void
1154     garbage_collect_ip_entries(void)
1155     {
1156     struct ip_entry *ptr;
1157     struct ip_entry *last_ptr;
1158     struct ip_entry *next_ptr;
1159     int i;
1160    
1161     for (i = 0; i < IP_HASH_SIZE; i++)
1162     {
1163     last_ptr = NULL;
1164    
1165     for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
1166     {
1167     next_ptr = ptr->next;
1168    
1169     if (ptr->count == 0 &&
1170     (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1171     {
1172     if (last_ptr != NULL)
1173     last_ptr->next = ptr->next;
1174     else
1175     ip_hash_table[i] = ptr->next;
1176     BlockHeapFree(ip_entry_heap, ptr);
1177     ip_entries_count--;
1178     }
1179     else
1180     last_ptr = ptr;
1181     }
1182     }
1183     }
1184    
1185     /* detach_conf()
1186     *
1187     * inputs - pointer to client to detach
1188     * - type of conf to detach
1189     * output - 0 for success, -1 for failure
1190     * side effects - Disassociate configuration from the client.
1191     * Also removes a class from the list if marked for deleting.
1192     */
1193     int
1194     detach_conf(struct Client *client_p, ConfType type)
1195     {
1196     dlink_node *ptr, *next_ptr;
1197     struct ConfItem *conf;
1198     struct ClassItem *aclass;
1199     struct AccessItem *aconf;
1200     struct ConfItem *aclass_conf;
1201    
1202     DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
1203     {
1204     conf = ptr->data;
1205    
1206     if (type == CONF_TYPE || conf->type == type)
1207     {
1208     dlinkDelete(ptr, &client_p->localClient->confs);
1209     free_dlink_node(ptr);
1210    
1211     switch (conf->type)
1212     {
1213     case CLIENT_TYPE:
1214     case OPER_TYPE:
1215     case SERVER_TYPE:
1216 michael 618 aconf = map_to_conf(conf);
1217 michael 671
1218 michael 672 assert(aconf->clients > 0);
1219 michael 671
1220 michael 1377 if ((aclass_conf = aconf->class_ptr) != NULL)
1221 adx 30 {
1222 michael 618 aclass = map_to_conf(aclass_conf);
1223 adx 30
1224 michael 672 assert(aclass->curr_user_count > 0);
1225    
1226 adx 30 if (conf->type == CLIENT_TYPE)
1227     remove_from_cidr_check(&client_p->localClient->ip, aclass);
1228 michael 672 if (--aclass->curr_user_count == 0 && aclass->active == 0)
1229 adx 30 delete_conf_item(aclass_conf);
1230     }
1231    
1232 michael 672 if (--aconf->clients == 0 && IsConfIllegal(aconf))
1233     delete_conf_item(conf);
1234    
1235 adx 30 break;
1236     default:
1237     break;
1238     }
1239    
1240     if (type != CONF_TYPE)
1241     return 0;
1242     }
1243     }
1244    
1245     return -1;
1246     }
1247    
1248     /* attach_conf()
1249     *
1250     * inputs - client pointer
1251     * - conf pointer
1252     * output -
1253     * side effects - Associate a specific configuration entry to a *local*
1254     * client (this is the one which used in accepting the
1255     * connection). Note, that this automatically changes the
1256     * attachment if there was an old one...
1257     */
1258     int
1259     attach_conf(struct Client *client_p, struct ConfItem *conf)
1260     {
1261 michael 1394 struct AccessItem *aconf = map_to_conf(conf);
1262     struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1263    
1264 adx 30 if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
1265     return 1;
1266    
1267 michael 1394 if (IsConfIllegal(aconf)) /* TBV: can't happen */
1268     return NOT_AUTHORIZED;
1269 adx 30
1270 michael 1394 if (conf->type == CLIENT_TYPE)
1271     if (cidr_limit_reached(IsConfExemptLimits(aconf),
1272     &client_p->localClient->ip, aclass))
1273     return TOO_MANY; /* Already at maximum allowed */
1274 adx 30
1275 michael 1394 aclass->curr_user_count++;
1276     aconf->clients++;
1277 adx 30
1278     dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
1279    
1280     return 0;
1281     }
1282    
1283     /* attach_connect_block()
1284     *
1285     * inputs - pointer to server to attach
1286     * - name of server
1287     * - hostname of server
1288     * output - true (1) if both are found, otherwise return false (0)
1289     * side effects - find connect block and attach them to connecting client
1290     */
1291     int
1292     attach_connect_block(struct Client *client_p, const char *name,
1293     const char *host)
1294     {
1295     dlink_node *ptr;
1296     struct ConfItem *conf;
1297     struct AccessItem *aconf;
1298    
1299     assert(client_p != NULL);
1300     assert(host != NULL);
1301    
1302     if (client_p == NULL || host == NULL)
1303     return 0;
1304    
1305     DLINK_FOREACH(ptr, server_items.head)
1306     {
1307     conf = ptr->data;
1308 michael 618 aconf = map_to_conf(conf);
1309 adx 30
1310     if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
1311     continue;
1312    
1313     attach_conf(client_p, conf);
1314     return -1;
1315     }
1316    
1317     return 0;
1318     }
1319    
1320     /* find_conf_exact()
1321     *
1322     * inputs - type of ConfItem
1323     * - pointer to name to find
1324     * - pointer to username to find
1325     * - pointer to host to find
1326     * output - NULL or pointer to conf found
1327     * side effects - find a conf entry which matches the hostname
1328     * and has the same name.
1329     */
1330     struct ConfItem *
1331     find_conf_exact(ConfType type, const char *name, const char *user,
1332     const char *host)
1333     {
1334     dlink_node *ptr;
1335     dlink_list *list_p;
1336     struct ConfItem *conf = NULL;
1337     struct AccessItem *aconf;
1338    
1339     /* Only valid for OPER_TYPE and ...? */
1340     list_p = map_to_list(type);
1341    
1342     DLINK_FOREACH(ptr, (*list_p).head)
1343     {
1344     conf = ptr->data;
1345    
1346     if (conf->name == NULL)
1347     continue;
1348 michael 815 aconf = map_to_conf(conf);
1349 adx 30 if (aconf->host == NULL)
1350     continue;
1351     if (irccmp(conf->name, name) != 0)
1352     continue;
1353    
1354     /*
1355     ** Accept if the *real* hostname (usually sockethost)
1356     ** socket host) matches *either* host or name field
1357     ** of the configuration.
1358     */
1359 michael 815 if (!match(aconf->host, host) || !match(aconf->user, user))
1360 adx 30 continue;
1361     if (type == OPER_TYPE)
1362     {
1363 michael 815 struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1364 adx 30
1365 michael 1377 if (aconf->clients >= aclass->max_total)
1366 adx 30 continue;
1367     }
1368 michael 815
1369     return conf;
1370 adx 30 }
1371 michael 815
1372 adx 30 return NULL;
1373     }
1374    
1375     /* find_conf_name()
1376     *
1377     * inputs - pointer to conf link list to search
1378     * - pointer to name to find
1379     * - int mask of type of conf to find
1380     * output - NULL or pointer to conf found
1381     * side effects - find a conf entry which matches the name
1382     * and has the given mask.
1383     */
1384     struct ConfItem *
1385     find_conf_name(dlink_list *list, const char *name, ConfType type)
1386     {
1387     dlink_node *ptr;
1388     struct ConfItem* conf;
1389    
1390     DLINK_FOREACH(ptr, list->head)
1391     {
1392     conf = ptr->data;
1393    
1394     if (conf->type == type)
1395     {
1396     if (conf->name && (irccmp(conf->name, name) == 0 ||
1397     match(conf->name, name)))
1398     return conf;
1399     }
1400     }
1401    
1402     return NULL;
1403     }
1404    
1405     /* map_to_list()
1406     *
1407     * inputs - ConfType conf
1408     * output - pointer to dlink_list to use
1409     * side effects - none
1410     */
1411     static dlink_list *
1412     map_to_list(ConfType type)
1413     {
1414     switch(type)
1415     {
1416     case RXLINE_TYPE:
1417     return(&rxconf_items);
1418     break;
1419     case XLINE_TYPE:
1420     return(&xconf_items);
1421     break;
1422     case ULINE_TYPE:
1423     return(&uconf_items);
1424     break;
1425     case NRESV_TYPE:
1426     return(&nresv_items);
1427     break;
1428     case OPER_TYPE:
1429     return(&oconf_items);
1430     break;
1431     case CLASS_TYPE:
1432     return(&class_items);
1433     break;
1434     case SERVER_TYPE:
1435     return(&server_items);
1436     break;
1437 michael 1172 case SERVICE_TYPE:
1438     return(&service_items);
1439     break;
1440 adx 30 case CLUSTER_TYPE:
1441     return(&cluster_items);
1442     break;
1443     case CONF_TYPE:
1444     case GLINE_TYPE:
1445     case KLINE_TYPE:
1446     case DLINE_TYPE:
1447     case CRESV_TYPE:
1448     default:
1449     return NULL;
1450     }
1451     }
1452    
1453     /* find_matching_name_conf()
1454     *
1455     * inputs - type of link list to look in
1456     * - pointer to name string to find
1457     * - pointer to user
1458     * - pointer to host
1459     * - optional action to match on as well
1460     * output - NULL or pointer to found struct MatchItem
1461     * side effects - looks for a match on name field
1462     */
1463     struct ConfItem *
1464     find_matching_name_conf(ConfType type, const char *name, const char *user,
1465     const char *host, int action)
1466     {
1467     dlink_node *ptr=NULL;
1468     struct ConfItem *conf=NULL;
1469     struct AccessItem *aconf=NULL;
1470     struct MatchItem *match_item=NULL;
1471     dlink_list *list_p = map_to_list(type);
1472    
1473     switch (type)
1474     {
1475 michael 1009 #ifdef HAVE_LIBPCRE
1476     case RXLINE_TYPE:
1477 adx 30 DLINK_FOREACH(ptr, list_p->head)
1478     {
1479     conf = ptr->data;
1480     assert(conf->regexpname);
1481    
1482     if (!ircd_pcre_exec(conf->regexpname, name))
1483     return conf;
1484     }
1485     break;
1486 michael 1009 #endif
1487 michael 1157 case SERVICE_TYPE:
1488     DLINK_FOREACH(ptr, list_p->head)
1489     {
1490     conf = ptr->data;
1491    
1492     if (EmptyString(conf->name))
1493     continue;
1494     if ((name != NULL) && !irccmp(name, conf->name))
1495     return conf;
1496     }
1497     break;
1498    
1499 adx 30 case XLINE_TYPE:
1500     case ULINE_TYPE:
1501     case NRESV_TYPE:
1502     DLINK_FOREACH(ptr, list_p->head)
1503     {
1504     conf = ptr->data;
1505    
1506     match_item = map_to_conf(conf);
1507     if (EmptyString(conf->name))
1508     continue;
1509     if ((name != NULL) && match_esc(conf->name, name))
1510     {
1511     if ((user == NULL && (host == NULL)))
1512     return conf;
1513     if ((match_item->action & action) != action)
1514     continue;
1515     if (EmptyString(match_item->user) || EmptyString(match_item->host))
1516     return conf;
1517     if (match(match_item->user, user) && match(match_item->host, host))
1518     return conf;
1519     }
1520     }
1521     break;
1522    
1523     case SERVER_TYPE:
1524     DLINK_FOREACH(ptr, list_p->head)
1525     {
1526     conf = ptr->data;
1527     aconf = map_to_conf(conf);
1528    
1529     if ((name != NULL) && match_esc(name, conf->name))
1530     return conf;
1531     else if ((host != NULL) && match_esc(host, aconf->host))
1532     return conf;
1533     }
1534     break;
1535    
1536     default:
1537     break;
1538     }
1539     return NULL;
1540     }
1541    
1542     /* find_exact_name_conf()
1543     *
1544     * inputs - type of link list to look in
1545     * - pointer to name string to find
1546     * - pointer to user
1547     * - pointer to host
1548     * output - NULL or pointer to found struct MatchItem
1549     * side effects - looks for an exact match on name field
1550     */
1551     struct ConfItem *
1552 michael 1285 find_exact_name_conf(ConfType type, const struct Client *who, const char *name,
1553 adx 30 const char *user, const char *host)
1554     {
1555     dlink_node *ptr = NULL;
1556     struct AccessItem *aconf;
1557     struct ConfItem *conf;
1558     struct MatchItem *match_item;
1559     dlink_list *list_p;
1560    
1561     list_p = map_to_list(type);
1562    
1563     switch(type)
1564     {
1565     case RXLINE_TYPE:
1566     case XLINE_TYPE:
1567     case ULINE_TYPE:
1568     case NRESV_TYPE:
1569    
1570     DLINK_FOREACH(ptr, list_p->head)
1571     {
1572     conf = ptr->data;
1573     match_item = (struct MatchItem *)map_to_conf(conf);
1574     if (EmptyString(conf->name))
1575     continue;
1576    
1577     if (irccmp(conf->name, name) == 0)
1578     {
1579     if ((user == NULL && (host == NULL)))
1580     return (conf);
1581     if (EmptyString(match_item->user) || EmptyString(match_item->host))
1582     return (conf);
1583     if (match(match_item->user, user) && match(match_item->host, host))
1584     return (conf);
1585     }
1586     }
1587     break;
1588    
1589     case OPER_TYPE:
1590     DLINK_FOREACH(ptr, list_p->head)
1591     {
1592     conf = ptr->data;
1593 michael 1285 aconf = map_to_conf(conf);
1594    
1595 adx 30 if (EmptyString(conf->name))
1596 michael 1285 continue;
1597    
1598     if (!irccmp(conf->name, name))
1599 adx 30 {
1600 michael 1285 if (!who)
1601     return conf;
1602     if (EmptyString(aconf->user) || EmptyString(aconf->host))
1603     return conf;
1604     if (match(aconf->user, who->username))
1605     {
1606     switch (aconf->type)
1607     {
1608     case HM_HOST:
1609     if (match(aconf->host, who->host) || match(aconf->host, who->sockhost))
1610     return conf;
1611     break;
1612     case HM_IPV4:
1613     if (who->localClient->aftype == AF_INET)
1614 michael 1389 if (match_ipv4(&who->localClient->ip, &aconf->addr, aconf->bits))
1615 michael 1285 return conf;
1616     break;
1617     #ifdef IPV6
1618     case HM_IPV6:
1619     if (who->localClient->aftype == AF_INET6)
1620 michael 1389 if (match_ipv6(&who->localClient->ip, &aconf->addr, aconf->bits))
1621 michael 1285 return conf;
1622     break;
1623     #endif
1624     default:
1625     assert(0);
1626     }
1627     }
1628 adx 30 }
1629     }
1630 michael 1285
1631 adx 30 break;
1632    
1633     case SERVER_TYPE:
1634     DLINK_FOREACH(ptr, list_p->head)
1635     {
1636     conf = ptr->data;
1637     aconf = (struct AccessItem *)map_to_conf(conf);
1638     if (EmptyString(conf->name))
1639     continue;
1640    
1641     if (name == NULL)
1642     {
1643     if (EmptyString(aconf->host))
1644     continue;
1645     if (irccmp(aconf->host, host) == 0)
1646     return(conf);
1647     }
1648     else if (irccmp(conf->name, name) == 0)
1649     {
1650     return (conf);
1651     }
1652     }
1653     break;
1654    
1655     case CLASS_TYPE:
1656     DLINK_FOREACH(ptr, list_p->head)
1657     {
1658     conf = ptr->data;
1659     if (EmptyString(conf->name))
1660     continue;
1661    
1662     if (irccmp(conf->name, name) == 0)
1663     return (conf);
1664     }
1665     break;
1666    
1667     default:
1668     break;
1669     }
1670     return(NULL);
1671     }
1672    
1673     /* rehash()
1674     *
1675     * Actual REHASH service routine. Called with sig == 0 if it has been called
1676     * as a result of an operator issuing this command, else assume it has been
1677     * called as a result of the server receiving a HUP signal.
1678     */
1679     int
1680     rehash(int sig)
1681     {
1682     if (sig != 0)
1683 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1684 adx 30 "Got signal SIGHUP, reloading ircd.conf file");
1685    
1686     restart_resolver();
1687 michael 1001
1688 adx 30 /* don't close listeners until we know we can go ahead with the rehash */
1689    
1690     /* Check to see if we magically got(or lost) IPv6 support */
1691     check_can_use_v6();
1692    
1693     read_conf_files(0);
1694    
1695     if (ServerInfo.description != NULL)
1696     strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1697    
1698     load_conf_modules();
1699    
1700     flush_deleted_I_P();
1701    
1702     rehashed_klines = 1;
1703 michael 1247 /* XXX */
1704 adx 30 if (ConfigLoggingEntry.use_logging)
1705 michael 1247 log_close_all();
1706 adx 30
1707     return(0);
1708     }
1709    
1710     /* set_default_conf()
1711     *
1712     * inputs - NONE
1713     * output - NONE
1714     * side effects - Set default values here.
1715     * This is called **PRIOR** to parsing the
1716     * configuration file. If you want to do some validation
1717     * of values later, put them in validate_conf().
1718     */
1719     static void
1720     set_default_conf(void)
1721     {
1722     /* verify init_class() ran, this should be an unnecessary check
1723     * but its not much work.
1724     */
1725     assert(class_default == (struct ConfItem *) class_items.tail->data);
1726    
1727     #ifdef HAVE_LIBCRYPTO
1728     ServerInfo.rsa_private_key = NULL;
1729     ServerInfo.rsa_private_key_file = NULL;
1730     #endif
1731    
1732     /* ServerInfo.name is not rehashable */
1733     /* ServerInfo.name = ServerInfo.name; */
1734     ServerInfo.description = NULL;
1735     DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1736     DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1737    
1738     memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1739     ServerInfo.specific_ipv4_vhost = 0;
1740     memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
1741     ServerInfo.specific_ipv6_vhost = 0;
1742    
1743     ServerInfo.max_clients = MAXCLIENTS_MAX;
1744 michael 956
1745     ServerInfo.hub = 0;
1746 adx 30 ServerInfo.dns_host.sin_addr.s_addr = 0;
1747     ServerInfo.dns_host.sin_port = 0;
1748     AdminInfo.name = NULL;
1749     AdminInfo.email = NULL;
1750     AdminInfo.description = NULL;
1751    
1752 michael 1247 log_close_all();
1753    
1754 adx 30 ConfigLoggingEntry.use_logging = 1;
1755    
1756 michael 1243 ConfigChannel.disable_fake_channels = 0;
1757     ConfigChannel.restrict_channels = 0;
1758 adx 30 ConfigChannel.knock_delay = 300;
1759     ConfigChannel.knock_delay_channel = 60;
1760 michael 1432 ConfigChannel.max_chans_per_user = 25;
1761 michael 1444 ConfigChannel.max_chans_per_oper = 50;
1762 michael 1243 ConfigChannel.quiet_on_ban = 1;
1763 adx 30 ConfigChannel.max_bans = 25;
1764     ConfigChannel.default_split_user_count = 0;
1765     ConfigChannel.default_split_server_count = 0;
1766 michael 1243 ConfigChannel.no_join_on_split = 0;
1767     ConfigChannel.no_create_on_split = 0;
1768 adx 30
1769 michael 1243 ConfigServerHide.flatten_links = 0;
1770 adx 30 ConfigServerHide.links_delay = 300;
1771 michael 1243 ConfigServerHide.hidden = 0;
1772     ConfigServerHide.hide_servers = 0;
1773 adx 30 DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1774 michael 1243 ConfigServerHide.hide_server_ips = 0;
1775 adx 30
1776 michael 876
1777 michael 1157 DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1778 michael 876 ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1779 michael 1459 ConfigFileEntry.glines = 0;
1780     ConfigFileEntry.gline_time = 12 * 3600;
1781     ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
1782 adx 30 ConfigFileEntry.gline_min_cidr = 16;
1783     ConfigFileEntry.gline_min_cidr6 = 48;
1784 michael 1243 ConfigFileEntry.invisible_on_connect = 1;
1785     ConfigFileEntry.tkline_expire_notices = 1;
1786     ConfigFileEntry.hide_spoof_ips = 1;
1787     ConfigFileEntry.ignore_bogus_ts = 0;
1788     ConfigFileEntry.disable_auth = 0;
1789     ConfigFileEntry.disable_remote = 0;
1790 adx 30 ConfigFileEntry.kill_chase_time_limit = 90;
1791 michael 1119 ConfigFileEntry.default_floodcount = 8;
1792 michael 1243 ConfigFileEntry.failed_oper_notice = 1;
1793 michael 1119 ConfigFileEntry.dots_in_ident = 0;
1794 adx 30 ConfigFileEntry.min_nonwildcard = 4;
1795     ConfigFileEntry.min_nonwildcard_simple = 3;
1796     ConfigFileEntry.max_accept = 20;
1797 michael 1243 ConfigFileEntry.anti_nick_flood = 0;
1798 adx 30 ConfigFileEntry.max_nick_time = 20;
1799     ConfigFileEntry.max_nick_changes = 5;
1800 michael 1119 ConfigFileEntry.anti_spam_exit_message_time = 0;
1801 adx 30 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1802 michael 1119 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1803 michael 1243 ConfigFileEntry.warn_no_nline = 1;
1804     ConfigFileEntry.stats_o_oper_only = 0;
1805 adx 30 ConfigFileEntry.stats_k_oper_only = 1; /* masked */
1806     ConfigFileEntry.stats_i_oper_only = 1; /* masked */
1807 michael 1243 ConfigFileEntry.stats_P_oper_only = 0;
1808 adx 30 ConfigFileEntry.caller_id_wait = 60;
1809 michael 1243 ConfigFileEntry.opers_bypass_callerid = 0;
1810 adx 30 ConfigFileEntry.pace_wait = 10;
1811     ConfigFileEntry.pace_wait_simple = 1;
1812 michael 1243 ConfigFileEntry.short_motd = 0;
1813     ConfigFileEntry.ping_cookie = 0;
1814     ConfigFileEntry.no_oper_flood = 0;
1815     ConfigFileEntry.true_no_oper_flood = 0;
1816     ConfigFileEntry.oper_pass_resv = 1;
1817 adx 30 ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1818 michael 1119 ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1819 adx 264 ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1820 michael 1119 UMODE_OPERWALL | UMODE_WALLOP;
1821 michael 1243 ConfigFileEntry.use_egd = 0;
1822 adx 30 ConfigFileEntry.egdpool_path = NULL;
1823     ConfigFileEntry.throttle_time = 10;
1824     }
1825    
1826     static void
1827     validate_conf(void)
1828     {
1829     if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1830     ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1831    
1832     if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1833     ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1834    
1835     if (ServerInfo.network_name == NULL)
1836     DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1837    
1838     if (ServerInfo.network_desc == NULL)
1839     DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1840    
1841 michael 1157 if (ConfigFileEntry.service_name == NULL)
1842     DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1843    
1844 michael 876 ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1845 adx 30 }
1846    
1847 michael 1363 /* read_conf()
1848     *
1849     * inputs - file descriptor pointing to config file to use
1850     * output - None
1851     * side effects - Read configuration file.
1852     */
1853     static void
1854     read_conf(FILE *file)
1855     {
1856     lineno = 0;
1857    
1858     set_default_conf(); /* Set default values prior to conf parsing */
1859     conf_parser_ctx.pass = 1;
1860     yyparse(); /* pick up the classes first */
1861    
1862     rewind(file);
1863    
1864     conf_parser_ctx.pass = 2;
1865     yyparse(); /* Load the values from the conf */
1866     validate_conf(); /* Check to make sure some values are still okay. */
1867     /* Some global values are also loaded here. */
1868     check_class(); /* Make sure classes are valid */
1869     }
1870    
1871 adx 30 /* lookup_confhost()
1872     *
1873     * start DNS lookups of all hostnames in the conf
1874     * line and convert an IP addresses in a.b.c.d number for to IP#s.
1875     */
1876     static void
1877     lookup_confhost(struct ConfItem *conf)
1878     {
1879     struct AccessItem *aconf;
1880     struct addrinfo hints, *res;
1881    
1882     aconf = map_to_conf(conf);
1883    
1884 michael 1413 if (has_wildcards(aconf->host))
1885 adx 30 {
1886 michael 1247 ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
1887 adx 30 aconf->host, conf->name);
1888     return;
1889     }
1890    
1891     /* Do name lookup now on hostnames given and store the
1892     * ip numbers in conf structure.
1893     */
1894     memset(&hints, 0, sizeof(hints));
1895    
1896     hints.ai_family = AF_UNSPEC;
1897     hints.ai_socktype = SOCK_STREAM;
1898    
1899     /* Get us ready for a bind() and don't bother doing dns lookup */
1900     hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1901    
1902 michael 1123 if (getaddrinfo(aconf->host, NULL, &hints, &res))
1903 adx 30 {
1904     conf_dns_lookup(aconf);
1905     return;
1906     }
1907    
1908     assert(res != NULL);
1909    
1910 michael 1389 memcpy(&aconf->addr, res->ai_addr, res->ai_addrlen);
1911     aconf->addr.ss_len = res->ai_addrlen;
1912     aconf->addr.ss.ss_family = res->ai_family;
1913 michael 1123 freeaddrinfo(res);
1914 adx 30 }
1915    
1916     /* conf_connect_allowed()
1917     *
1918     * inputs - pointer to inaddr
1919     * - int type ipv4 or ipv6
1920     * output - BANNED or accepted
1921     * side effects - none
1922     */
1923     int
1924     conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1925     {
1926     struct ip_entry *ip_found;
1927     struct AccessItem *aconf = find_dline_conf(addr, aftype);
1928    
1929     /* DLINE exempt also gets you out of static limits/pacing... */
1930     if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1931     return 0;
1932    
1933     if (aconf != NULL)
1934     return BANNED_CLIENT;
1935    
1936     ip_found = find_or_add_ip(addr);
1937    
1938     if ((CurrentTime - ip_found->last_attempt) <
1939     ConfigFileEntry.throttle_time)
1940     {
1941     ip_found->last_attempt = CurrentTime;
1942     return TOO_FAST;
1943     }
1944    
1945     ip_found->last_attempt = CurrentTime;
1946     return 0;
1947     }
1948    
1949     static struct AccessItem *
1950     find_regexp_kline(const char *uhi[])
1951     {
1952 michael 1009 #ifdef HAVE_LIBPCRE
1953 adx 30 const dlink_node *ptr = NULL;
1954    
1955     DLINK_FOREACH(ptr, rkconf_items.head)
1956     {
1957     struct AccessItem *aptr = map_to_conf(ptr->data);
1958    
1959     assert(aptr->regexuser);
1960     assert(aptr->regexhost);
1961    
1962     if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
1963     (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
1964     !ircd_pcre_exec(aptr->regexhost, uhi[2])))
1965     return aptr;
1966     }
1967 michael 1009 #endif
1968 adx 30 return NULL;
1969     }
1970    
1971     /* find_kill()
1972     *
1973     * inputs - pointer to client structure
1974     * output - pointer to struct AccessItem if found
1975     * side effects - See if this user is klined already,
1976     * and if so, return struct AccessItem pointer
1977     */
1978     struct AccessItem *
1979     find_kill(struct Client *client_p)
1980     {
1981     struct AccessItem *aconf = NULL;
1982     const char *uhi[3];
1983    
1984     uhi[0] = client_p->username;
1985     uhi[1] = client_p->host;
1986     uhi[2] = client_p->sockhost;
1987    
1988     assert(client_p != NULL);
1989    
1990 michael 1393 aconf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1991     CONF_KLINE, client_p->localClient->aftype,
1992     client_p->username, NULL, 1);
1993 adx 30 if (aconf == NULL)
1994     aconf = find_regexp_kline(uhi);
1995    
1996 michael 1393 return aconf;
1997 adx 30 }
1998    
1999     struct AccessItem *
2000     find_gline(struct Client *client_p)
2001     {
2002     struct AccessItem *aconf;
2003    
2004     assert(client_p != NULL);
2005    
2006 michael 1393 aconf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
2007     CONF_GLINE, client_p->localClient->aftype,
2008     client_p->username, NULL, 1);
2009     return aconf;
2010 adx 30 }
2011    
2012     /* add_temp_line()
2013     *
2014     * inputs - pointer to struct ConfItem
2015     * output - none
2016     * Side effects - links in given struct ConfItem into
2017     * temporary *line link list
2018     */
2019     void
2020     add_temp_line(struct ConfItem *conf)
2021     {
2022 michael 1622 if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2023 adx 30 {
2024     conf->flags |= CONF_FLAGS_TEMPORARY;
2025     dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2026     }
2027     }
2028    
2029     /* cleanup_tklines()
2030     *
2031     * inputs - NONE
2032     * output - NONE
2033     * side effects - call function to expire temporary k/d lines
2034     * This is an event started off in ircd.c
2035     */
2036     void
2037     cleanup_tklines(void *notused)
2038     {
2039 michael 1369 hostmask_expire_temporary();
2040 michael 1622 expire_tklines(&xconf_items);
2041 adx 30 expire_tklines(&temporary_resv);
2042     }
2043    
2044     /* expire_tklines()
2045     *
2046     * inputs - tkline list pointer
2047     * output - NONE
2048     * side effects - expire tklines
2049     */
2050     static void
2051     expire_tklines(dlink_list *tklist)
2052     {
2053     dlink_node *ptr;
2054     dlink_node *next_ptr;
2055     struct ConfItem *conf;
2056     struct MatchItem *xconf;
2057     struct MatchItem *nconf;
2058     struct ResvChannel *cconf;
2059    
2060     DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
2061     {
2062     conf = ptr->data;
2063    
2064 michael 1369 if (conf->type == XLINE_TYPE)
2065 adx 30 {
2066 michael 1622 if (!IsConfTemporary(conf))
2067     continue;
2068    
2069 adx 30 xconf = (struct MatchItem *)map_to_conf(conf);
2070     if (xconf->hold <= CurrentTime)
2071     {
2072     if (ConfigFileEntry.tkline_expire_notices)
2073 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2074     "Temporary X-line for [%s] expired", conf->name);
2075 adx 30 delete_conf_item(conf);
2076     }
2077     }
2078     else if (conf->type == NRESV_TYPE)
2079     {
2080     nconf = (struct MatchItem *)map_to_conf(conf);
2081     if (nconf->hold <= CurrentTime)
2082     {
2083     if (ConfigFileEntry.tkline_expire_notices)
2084 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2085 adx 30 "Temporary RESV for [%s] expired", conf->name);
2086     dlinkDelete(ptr, tklist);
2087     free_dlink_node(ptr);
2088     delete_conf_item(conf);
2089     }
2090     }
2091     else if (conf->type == CRESV_TYPE)
2092     {
2093     cconf = (struct ResvChannel *)map_to_conf(conf);
2094     if (cconf->hold <= CurrentTime)
2095     {
2096     if (ConfigFileEntry.tkline_expire_notices)
2097 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2098 adx 30 "Temporary RESV for [%s] expired", cconf->name);
2099 db 855 delete_channel_resv(cconf);
2100 adx 30 }
2101     }
2102     }
2103     }
2104    
2105     /* oper_privs_as_string()
2106     *
2107 michael 58 * inputs - pointer to client_p
2108 adx 30 * output - pointer to static string showing oper privs
2109     * side effects - return as string, the oper privs as derived from port
2110     */
2111 michael 58 static const struct oper_privs
2112     {
2113     const unsigned int oprivs;
2114     const unsigned char c;
2115     } flag_list[] = {
2116 michael 1294 { OPER_FLAG_ADMIN, 'A' },
2117     { OPER_FLAG_REMOTEBAN, 'B' },
2118     { OPER_FLAG_DIE, 'D' },
2119     { OPER_FLAG_GLINE, 'G' },
2120     { OPER_FLAG_REHASH, 'H' },
2121     { OPER_FLAG_K, 'K' },
2122     { OPER_FLAG_OPERWALL, 'L' },
2123     { OPER_FLAG_N, 'N' },
2124     { OPER_FLAG_GLOBAL_KILL, 'O' },
2125     { OPER_FLAG_REMOTE, 'R' },
2126     { OPER_FLAG_OPER_SPY, 'S' },
2127     { OPER_FLAG_UNKLINE, 'U' },
2128     { OPER_FLAG_X, 'X' },
2129     { 0, '\0' }
2130 michael 58 };
2131 adx 30
2132     char *
2133     oper_privs_as_string(const unsigned int port)
2134     {
2135 michael 58 static char privs_out[16];
2136     char *privs_ptr = privs_out;
2137     unsigned int i = 0;
2138 adx 30
2139 michael 58 for (; flag_list[i].oprivs; ++i)
2140     {
2141 michael 1294 if (port & flag_list[i].oprivs)
2142 michael 58 *privs_ptr++ = flag_list[i].c;
2143     else
2144     *privs_ptr++ = ToLowerTab[flag_list[i].c];
2145     }
2146    
2147     *privs_ptr = '\0';
2148    
2149 adx 30 return privs_out;
2150     }
2151    
2152     /*
2153     * Input: A client to find the active oper{} name for.
2154     * Output: The nick!user@host{oper} of the oper.
2155     * "oper" is server name for remote opers
2156     * Side effects: None.
2157     */
2158 michael 1364 const char *
2159 adx 30 get_oper_name(const struct Client *client_p)
2160     {
2161 michael 1364 dlink_node *cnode = NULL;
2162 adx 30 /* +5 for !,@,{,} and null */
2163 michael 1147 static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
2164 adx 30
2165     if (MyConnect(client_p))
2166     {
2167 michael 1364 if ((cnode = client_p->localClient->confs.head))
2168 adx 30 {
2169 michael 1364 struct ConfItem *conf = cnode->data;
2170     const struct AccessItem *aconf = map_to_conf(conf);
2171 adx 30
2172     if (IsConfOperator(aconf))
2173     {
2174 michael 1147 snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
2175     client_p->username, client_p->host, conf->name);
2176 adx 30 return buffer;
2177     }
2178     }
2179    
2180     /* Probably should assert here for now. If there is an oper out there
2181     * with no oper{} conf attached, it would be good for us to know...
2182     */
2183     assert(0); /* Oper without oper conf! */
2184     }
2185    
2186 michael 1147 snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
2187     client_p->username, client_p->host, client_p->servptr->name);
2188 adx 30 return buffer;
2189     }
2190    
2191     /* read_conf_files()
2192     *
2193     * inputs - cold start YES or NO
2194     * output - none
2195     * side effects - read all conf files needed, ircd.conf kline.conf etc.
2196     */
2197     void
2198     read_conf_files(int cold)
2199     {
2200     const char *filename;
2201     char chanmodes[32];
2202     char chanlimit[32];
2203    
2204 michael 967 conf_parser_ctx.boot = cold;
2205 michael 1622 filename = ConfigFileEntry.configfile;
2206 adx 30
2207     /* We need to know the initial filename for the yyerror() to report
2208     FIXME: The full path is in conffilenamebuf first time since we
2209     dont know anything else
2210    
2211     - Gozem 2002-07-21
2212     */
2213     strlcpy(conffilebuf, filename, sizeof(conffilebuf));
2214    
2215 michael 1325 if ((conf_parser_ctx.conf_file = fopen(filename, "r")) == NULL)
2216 adx 30 {
2217     if (cold)
2218     {
2219 michael 1247 ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2220 adx 30 filename, strerror(errno));
2221     exit(-1);
2222     }
2223     else
2224     {
2225 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2226 adx 30 "Unable to read configuration file '%s': %s",
2227     filename, strerror(errno));
2228     return;
2229     }
2230     }
2231    
2232     if (!cold)
2233     clear_out_old_conf();
2234    
2235 michael 967 read_conf(conf_parser_ctx.conf_file);
2236 michael 1325 fclose(conf_parser_ctx.conf_file);
2237 adx 30
2238     add_isupport("NETWORK", ServerInfo.network_name, -1);
2239 michael 1495 snprintf(chanmodes, sizeof(chanmodes), "beI:%d",
2240     ConfigChannel.max_bans);
2241 adx 30 add_isupport("MAXLIST", chanmodes, -1);
2242     add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
2243 michael 1147
2244 michael 1474 add_isupport("CHANTYPES", "#", -1);
2245 michael 1147
2246 michael 1474 snprintf(chanlimit, sizeof(chanlimit), "#:%d",
2247 michael 1147 ConfigChannel.max_chans_per_user);
2248 adx 30 add_isupport("CHANLIMIT", chanlimit, -1);
2249 michael 1495 snprintf(chanmodes, sizeof(chanmodes), "%s",
2250     "beI,k,l,imnprstORS");
2251 michael 100 add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2252 michael 1147
2253 michael 1495 add_isupport("EXCEPTS", "e", -1);
2254     add_isupport("INVEX", "I", -1);
2255 adx 30 add_isupport("CHANMODES", chanmodes, -1);
2256    
2257     /*
2258     * message_locale may have changed. rebuild isupport since it relies
2259     * on strlen(form_str(RPL_ISUPPORT))
2260     */
2261     rebuild_isupport_message_line();
2262     }
2263    
2264     /* clear_out_old_conf()
2265     *
2266     * inputs - none
2267     * output - none
2268     * side effects - Clear out the old configuration
2269     */
2270     static void
2271     clear_out_old_conf(void)
2272     {
2273     dlink_node *ptr = NULL, *next_ptr = NULL;
2274     struct ConfItem *conf;
2275     struct AccessItem *aconf;
2276     struct ClassItem *cltmp;
2277     dlink_list *free_items [] = {
2278 michael 1383 &server_items, &oconf_items,
2279 adx 30 &uconf_items, &xconf_items, &rxconf_items, &rkconf_items,
2280 michael 1459 &nresv_items, &cluster_items, &service_items, NULL
2281 adx 30 };
2282    
2283     dlink_list ** iterator = free_items; /* C is dumb */
2284    
2285     /* We only need to free anything allocated by yyparse() here.
2286     * Resetting structs, etc, is taken care of by set_default_conf().
2287     */
2288    
2289     for (; *iterator != NULL; iterator++)
2290     {
2291     DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2292     {
2293     conf = ptr->data;
2294     /* XXX This is less than pretty */
2295     if (conf->type == SERVER_TYPE)
2296     {
2297 michael 671 aconf = map_to_conf(conf);
2298    
2299 adx 30 if (aconf->clients != 0)
2300     {
2301     SetConfIllegal(aconf);
2302     dlinkDelete(&conf->node, &server_items);
2303     }
2304     else
2305     {
2306     delete_conf_item(conf);
2307     }
2308     }
2309     else if (conf->type == OPER_TYPE)
2310     {
2311 michael 671 aconf = map_to_conf(conf);
2312    
2313 adx 30 if (aconf->clients != 0)
2314     {
2315     SetConfIllegal(aconf);
2316     dlinkDelete(&conf->node, &oconf_items);
2317     }
2318     else
2319     {
2320     delete_conf_item(conf);
2321     }
2322     }
2323     else if (conf->type == XLINE_TYPE ||
2324     conf->type == RXLINE_TYPE ||
2325     conf->type == RKLINE_TYPE)
2326     {
2327     /* temporary (r)xlines are also on
2328     * the (r)xconf items list */
2329     if (conf->flags & CONF_FLAGS_TEMPORARY)
2330     continue;
2331    
2332     delete_conf_item(conf);
2333     }
2334     else
2335     {
2336     delete_conf_item(conf);
2337     }
2338     }
2339     }
2340    
2341 michael 671 /*
2342     * don't delete the class table, rather mark all entries
2343 adx 30 * for deletion. The table is cleaned up by check_class. - avalon
2344     */
2345     DLINK_FOREACH(ptr, class_items.head)
2346     {
2347 michael 671 cltmp = map_to_conf(ptr->data);
2348    
2349 adx 30 if (ptr != class_items.tail) /* never mark the "default" class */
2350 michael 671 cltmp->active = 0;
2351 adx 30 }
2352    
2353     clear_out_address_conf();
2354    
2355     /* clean out module paths */
2356     mod_clear_paths();
2357    
2358     /* clean out ServerInfo */
2359     MyFree(ServerInfo.description);
2360     ServerInfo.description = NULL;
2361     MyFree(ServerInfo.network_name);
2362     ServerInfo.network_name = NULL;
2363     MyFree(ServerInfo.network_desc);
2364     ServerInfo.network_desc = NULL;
2365     MyFree(ConfigFileEntry.egdpool_path);
2366     ConfigFileEntry.egdpool_path = NULL;
2367     #ifdef HAVE_LIBCRYPTO
2368     if (ServerInfo.rsa_private_key != NULL)
2369     {
2370     RSA_free(ServerInfo.rsa_private_key);
2371     ServerInfo.rsa_private_key = NULL;
2372     }
2373    
2374     MyFree(ServerInfo.rsa_private_key_file);
2375     ServerInfo.rsa_private_key_file = NULL;
2376 michael 1316
2377     if (ServerInfo.server_ctx)
2378     SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
2379     SSL_OP_NO_SSLv3|
2380     SSL_OP_NO_TLSv1);
2381     if (ServerInfo.client_ctx)
2382     SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
2383     SSL_OP_NO_SSLv3|
2384     SSL_OP_NO_TLSv1);
2385 adx 30 #endif
2386    
2387     /* clean out old resvs from the conf */
2388     clear_conf_resv();
2389    
2390     /* clean out AdminInfo */
2391     MyFree(AdminInfo.name);
2392     AdminInfo.name = NULL;
2393     MyFree(AdminInfo.email);
2394     AdminInfo.email = NULL;
2395     MyFree(AdminInfo.description);
2396     AdminInfo.description = NULL;
2397    
2398     /* operator{} and class{} blocks are freed above */
2399     /* clean out listeners */
2400     close_listeners();
2401    
2402     /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2403     * exempt{} and gecos{} blocks are freed above too
2404     */
2405    
2406     /* clean out general */
2407 michael 1157 MyFree(ConfigFileEntry.service_name);
2408     ConfigFileEntry.service_name = NULL;
2409    
2410 adx 30 delete_isupport("INVEX");
2411     delete_isupport("EXCEPTS");
2412     }
2413    
2414     /* flush_deleted_I_P()
2415     *
2416     * inputs - none
2417     * output - none
2418     * side effects - This function removes I/P conf items
2419     */
2420     static void
2421     flush_deleted_I_P(void)
2422     {
2423     dlink_node *ptr;
2424     dlink_node *next_ptr;
2425     struct ConfItem *conf;
2426     struct AccessItem *aconf;
2427     dlink_list * free_items [] = {
2428 db 151 &server_items, &oconf_items, NULL
2429 adx 30 };
2430     dlink_list ** iterator = free_items; /* C is dumb */
2431    
2432     /* flush out deleted I and P lines
2433     * although still in use.
2434     */
2435     for (; *iterator != NULL; iterator++)
2436     {
2437     DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2438     {
2439     conf = ptr->data;
2440     aconf = (struct AccessItem *)map_to_conf(conf);
2441    
2442     if (IsConfIllegal(aconf))
2443     {
2444     dlinkDelete(ptr, *iterator);
2445    
2446     if (aconf->clients == 0)
2447     delete_conf_item(conf);
2448     }
2449     }
2450     }
2451     }
2452    
2453     #define BAD_PING (-1)
2454    
2455     /* get_conf_ping()
2456     *
2457     * inputs - pointer to struct AccessItem
2458     * - pointer to a variable that receives ping warning time
2459     * output - ping frequency
2460     * side effects - NONE
2461     */
2462     static int
2463     get_conf_ping(struct ConfItem *conf, int *pingwarn)
2464     {
2465     struct ClassItem *aclass;
2466     struct AccessItem *aconf;
2467    
2468     if (conf != NULL)
2469     {
2470     aconf = (struct AccessItem *)map_to_conf(conf);
2471     if (aconf->class_ptr != NULL)
2472     {
2473     aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2474 michael 1377 *pingwarn = aclass->ping_warning;
2475     return aclass->ping_freq;
2476 adx 30 }
2477     }
2478    
2479     return BAD_PING;
2480     }
2481    
2482     /* get_client_class()
2483     *
2484     * inputs - pointer to client struct
2485     * output - pointer to name of class
2486     * side effects - NONE
2487     */
2488     const char *
2489     get_client_class(struct Client *target_p)
2490     {
2491 michael 1387 dlink_node *cnode = NULL;
2492     struct AccessItem *aconf = NULL;
2493 adx 30
2494 michael 1387 assert(!IsMe(target_p));
2495    
2496     if ((cnode = target_p->localClient->confs.head))
2497 adx 30 {
2498 michael 1387 struct ConfItem *conf = cnode->data;
2499 adx 30
2500 michael 1387 assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2501     (conf->type == OPER_TYPE));
2502    
2503     aconf = map_to_conf(conf);
2504     if (aconf->class_ptr != NULL)
2505     return aconf->class_ptr->name;
2506 adx 30 }
2507    
2508     return "default";
2509     }
2510    
2511     /* get_client_ping()
2512     *
2513     * inputs - pointer to client struct
2514     * - pointer to a variable that receives ping warning time
2515     * output - ping frequency
2516     * side effects - NONE
2517     */
2518     int
2519     get_client_ping(struct Client *target_p, int *pingwarn)
2520     {
2521 michael 1387 int ping = 0;
2522     dlink_node *cnode = NULL;
2523 adx 30
2524 michael 1387 if ((cnode = target_p->localClient->confs.head))
2525     {
2526     struct ConfItem *conf = cnode->data;
2527 adx 30
2528 michael 1387 assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2529     (conf->type == OPER_TYPE));
2530 adx 30
2531 michael 1387 ping = get_conf_ping(conf, pingwarn);
2532     if (ping > 0)
2533     return ping;
2534     }
2535    
2536 adx 30 *pingwarn = 0;
2537     return DEFAULT_PINGFREQUENCY;
2538     }
2539    
2540     /* find_class()
2541     *
2542     * inputs - string name of class
2543     * output - corresponding Class pointer
2544     * side effects - NONE
2545     */
2546     struct ConfItem *
2547     find_class(const char *classname)
2548     {
2549     struct ConfItem *conf;
2550    
2551 michael 1285 if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2552 michael 671 return conf;
2553 adx 30
2554     return class_default;
2555     }
2556    
2557     /* check_class()
2558     *
2559     * inputs - NONE
2560     * output - NONE
2561     * side effects -
2562     */
2563     void
2564     check_class(void)
2565     {
2566 michael 671 dlink_node *ptr = NULL, *next_ptr = NULL;
2567 adx 30
2568     DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2569     {
2570 michael 671 struct ClassItem *aclass = map_to_conf(ptr->data);
2571 adx 30
2572 michael 1377 if (!aclass->active && !aclass->curr_user_count)
2573 adx 30 {
2574     destroy_cidr_class(aclass);
2575 michael 673 delete_conf_item(ptr->data);
2576 adx 30 }
2577     }
2578     }
2579    
2580     /* init_class()
2581     *
2582     * inputs - NONE
2583     * output - NONE
2584     * side effects -
2585     */
2586     void
2587     init_class(void)
2588     {
2589     struct ClassItem *aclass;
2590    
2591     class_default = make_conf_item(CLASS_TYPE);
2592 michael 671
2593     aclass = map_to_conf(class_default);
2594     aclass->active = 1;
2595 adx 30 DupString(class_default->name, "default");
2596 michael 1377 aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
2597     aclass->ping_freq = DEFAULT_PINGFREQUENCY;
2598     aclass->max_total = MAXIMUM_LINKS_DEFAULT;
2599     aclass->max_sendq = DEFAULT_SENDQ;
2600 michael 1516 aclass->max_recvq = DEFAULT_RECVQ;
2601 adx 30
2602     client_check_cb = register_callback("check_client", check_client);
2603     }
2604    
2605     /* get_sendq()
2606     *
2607     * inputs - pointer to client
2608     * output - sendq for this client as found from its class
2609     * side effects - NONE
2610     */
2611 michael 948 unsigned int
2612 adx 30 get_sendq(struct Client *client_p)
2613     {
2614 michael 948 unsigned int sendq = DEFAULT_SENDQ;
2615 michael 1387 dlink_node *cnode;
2616 adx 30 struct ConfItem *class_conf;
2617     struct ClassItem *aclass;
2618     struct AccessItem *aconf;
2619    
2620 michael 1388 assert(!IsMe(client_p));
2621 michael 1387
2622     if ((cnode = client_p->localClient->confs.head))
2623 adx 30 {
2624 michael 1387 struct ConfItem *conf = cnode->data;
2625    
2626     assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2627     (conf->type == OPER_TYPE));
2628    
2629     aconf = map_to_conf(conf);
2630    
2631     if ((class_conf = aconf->class_ptr) == NULL)
2632     return DEFAULT_SENDQ; /* TBV: shouldn't be possible at all */
2633    
2634     aclass = map_to_conf(class_conf);
2635     sendq = aclass->max_sendq;
2636     return sendq;
2637 adx 30 }
2638 michael 1387
2639 adx 30 /* XXX return a default?
2640     * if here, then there wasn't an attached conf with a sendq
2641     * that is very bad -Dianora
2642     */
2643     return DEFAULT_SENDQ;
2644     }
2645    
2646 michael 1516 unsigned int
2647     get_recvq(struct Client *client_p)
2648     {
2649     unsigned int recvq = DEFAULT_RECVQ;
2650     dlink_node *cnode;
2651     struct ConfItem *class_conf;
2652     struct ClassItem *aclass;
2653     struct AccessItem *aconf;
2654    
2655     assert(!IsMe(client_p));
2656    
2657     if ((cnode = client_p->localClient->confs.head))
2658     {
2659     struct ConfItem *conf = cnode->data;
2660    
2661     assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2662     (conf->type == OPER_TYPE));
2663    
2664     aconf = map_to_conf(conf);
2665    
2666     if ((class_conf = aconf->class_ptr) == NULL)
2667     return DEFAULT_RECVQ; /* TBV: shouldn't be possible at all */
2668    
2669     aclass = map_to_conf(class_conf);
2670     recvq = aclass->max_recvq;
2671     return recvq;
2672     }
2673    
2674     /* XXX return a default?
2675     * if here, then there wasn't an attached conf with a recvq
2676     * that is very bad -Dianora
2677     */
2678     return DEFAULT_RECVQ;
2679     }
2680    
2681 adx 30 /* conf_add_class_to_conf()
2682     *
2683     * inputs - pointer to config item
2684     * output - NONE
2685     * side effects - Add a class pointer to a conf
2686     */
2687     void
2688     conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
2689     {
2690 michael 671 struct AccessItem *aconf = map_to_conf(conf);
2691     struct ClassItem *class = NULL;
2692 adx 30
2693     if (class_name == NULL)
2694     {
2695     aconf->class_ptr = class_default;
2696 michael 671
2697 adx 30 if (conf->type == CLIENT_TYPE)
2698 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2699 adx 30 "Warning *** Defaulting to default class for %s@%s",
2700     aconf->user, aconf->host);
2701     else
2702 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2703 adx 30 "Warning *** Defaulting to default class for %s",
2704     conf->name);
2705     }
2706     else
2707     aconf->class_ptr = find_class(class_name);
2708    
2709 michael 671 if (aconf->class_ptr)
2710     class = map_to_conf(aconf->class_ptr);
2711    
2712     if (aconf->class_ptr == NULL || !class->active)
2713 adx 30 {
2714     if (conf->type == CLIENT_TYPE)
2715 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2716 adx 30 "Warning *** Defaulting to default class for %s@%s",
2717     aconf->user, aconf->host);
2718     else
2719 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2720 adx 30 "Warning *** Defaulting to default class for %s",
2721     conf->name);
2722     aconf->class_ptr = class_default;
2723     }
2724     }
2725    
2726     /* conf_add_server()
2727     *
2728     * inputs - pointer to config item
2729     * - pointer to link count already on this conf
2730     * output - NONE
2731     * side effects - Add a connect block
2732     */
2733     int
2734 michael 593 conf_add_server(struct ConfItem *conf, const char *class_name)
2735 adx 30 {
2736 michael 1366 struct AccessItem *aconf = map_to_conf(conf);
2737 adx 30
2738     conf_add_class_to_conf(conf, class_name);
2739    
2740 michael 593 if (!aconf->host || !conf->name)
2741 adx 30 {
2742 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2743     "Bad connect block");
2744 michael 1247 ilog(LOG_TYPE_IRCD, "Bad connect block");
2745 adx 30 return -1;
2746     }
2747    
2748 michael 1302 if (EmptyString(aconf->passwd))
2749 adx 30 {
2750 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2751     "Bad connect block, name %s",
2752 adx 30 conf->name);
2753 michael 1247 ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
2754 adx 30 return -1;
2755     }
2756    
2757     lookup_confhost(conf);
2758    
2759     return 0;
2760     }
2761    
2762     /* yyerror()
2763     *
2764     * inputs - message from parser
2765     * output - NONE
2766     * side effects - message to opers and log file entry is made
2767     */
2768     void
2769     yyerror(const char *msg)
2770     {
2771     char newlinebuf[IRCD_BUFSIZE];
2772    
2773 michael 967 if (conf_parser_ctx.pass != 1)
2774 adx 30 return;
2775    
2776     strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
2777 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
2778     "\"%s\", line %u: %s: %s",
2779 adx 30 conffilebuf, lineno + 1, msg, newlinebuf);
2780 michael 1247 ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
2781 adx 30 conffilebuf, lineno + 1, msg, newlinebuf);
2782     }
2783    
2784     /*
2785     * valid_tkline()
2786     *
2787     * inputs - pointer to ascii string to check
2788     * - whether the specified time is in seconds or minutes
2789     * output - -1 not enough parameters
2790     * - 0 if not an integer number, else the number
2791     * side effects - none
2792     * Originally written by Dianora (Diane, db@db.net)
2793     */
2794     time_t
2795 michael 1120 valid_tkline(const char *p, int minutes)
2796 adx 30 {
2797     time_t result = 0;
2798    
2799 michael 1120 for (; *p; ++p)
2800 adx 30 {
2801 michael 1120 if (!IsDigit(*p))
2802 michael 1121 return 0;
2803 michael 1120
2804     result *= 10;
2805     result += ((*p) & 0xF);
2806 adx 30 }
2807    
2808 michael 1120 /*
2809     * In the degenerate case where oper does a /quote kline 0 user@host :reason
2810 adx 30 * i.e. they specifically use 0, I am going to return 1 instead
2811     * as a return value of non-zero is used to flag it as a temporary kline
2812     */
2813     if (result == 0)
2814     result = 1;
2815    
2816     /*
2817     * If the incoming time is in seconds convert it to minutes for the purpose
2818     * of this calculation
2819     */
2820     if (!minutes)
2821     result = result / (time_t)60;
2822    
2823     if (result > MAX_TDKLINE_TIME)
2824     result = MAX_TDKLINE_TIME;
2825    
2826     result = result * (time_t)60; /* turn it into seconds */
2827    
2828     return result;
2829     }
2830    
2831     /* valid_wild_card()
2832     *
2833     * input - pointer to client
2834     * - int flag, 0 for no warning oper 1 for warning oper
2835     * - count of following varargs to check
2836     * output - 0 if not valid, 1 if valid
2837     * side effects - NOTICE is given to source_p if warn is 1
2838     */
2839     int
2840     valid_wild_card(struct Client *source_p, int warn, int count, ...)
2841     {
2842     char *p;
2843     char tmpch;
2844     int nonwild = 0;
2845     va_list args;
2846    
2847     /*
2848     * Now we must check the user and host to make sure there
2849     * are at least NONWILDCHARS non-wildcard characters in
2850     * them, otherwise assume they are attempting to kline
2851     * *@* or some variant of that. This code will also catch
2852     * people attempting to kline *@*.tld, as long as NONWILDCHARS
2853     * is greater than 3. In that case, there are only 3 non-wild
2854     * characters (tld), so if NONWILDCHARS is 4, the kline will
2855     * be disallowed.
2856     * -wnder
2857     */
2858    
2859     va_start(args, count);
2860    
2861     while (count--)
2862     {
2863     p = va_arg(args, char *);
2864     if (p == NULL)
2865     continue;
2866    
2867     while ((tmpch = *p++))
2868     {
2869     if (!IsKWildChar(tmpch))
2870     {
2871     /*
2872     * If we find enough non-wild characters, we can
2873     * break - no point in searching further.
2874     */
2875     if (++nonwild >= ConfigFileEntry.min_nonwildcard)
2876     return 1;
2877     }
2878     }
2879     }
2880    
2881     if (warn)
2882     sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
2883     me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
2884     return 0;
2885     }
2886    
2887     /* XXX should this go into a separate file ? -Dianora */
2888     /* parse_aline
2889     *
2890     * input - pointer to cmd name being used
2891     * - pointer to client using cmd
2892     * - parc parameter count
2893     * - parv[] list of parameters to parse
2894     * - parse_flags bit map of things to test
2895     * - pointer to user or string to parse into
2896     * - pointer to host or NULL to parse into if non NULL
2897     * - pointer to optional tkline time or NULL
2898     * - pointer to target_server to parse into if non NULL
2899     * - pointer to reason to parse into
2900     *
2901     * output - 1 if valid, -1 if not valid
2902     * side effects - A generalised k/d/x etc. line parser,
2903     * "ALINE [time] user@host|string [ON] target :reason"
2904     * will parse returning a parsed user, host if
2905     * h_p pointer is non NULL, string otherwise.
2906     * if tkline_time pointer is non NULL a tk line will be set
2907     * to non zero if found.
2908     * if tkline_time pointer is NULL and tk line is found,
2909     * error is reported.
2910     * if target_server is NULL and an "ON" is found error
2911     * is reported.
2912     * if reason pointer is NULL ignore pointer,
2913 db 936 * this allows use of parse_a_line in unkline etc.
2914 adx 30 *
2915     * - Dianora
2916     */
2917     int
2918     parse_aline(const char *cmd, struct Client *source_p,
2919     int parc, char **parv,
2920     int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
2921     char **target_server, char **reason)
2922     {
2923     int found_tkline_time=0;
2924     static char def_reason[] = "No Reason";
2925     static char user[USERLEN*4+1];
2926     static char host[HOSTLEN*4+1];
2927    
2928     parv++;
2929     parc--;
2930    
2931     found_tkline_time = valid_tkline(*parv, TK_MINUTES);
2932    
2933     if (found_tkline_time != 0)
2934     {
2935     parv++;
2936     parc--;
2937    
2938     if (tkline_time != NULL)
2939     *tkline_time = found_tkline_time;
2940     else
2941     {
2942     sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
2943     me.name, source_p->name, cmd);
2944     return -1;
2945     }
2946     }
2947    
2948     if (parc == 0)
2949     {
2950     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
2951     me.name, source_p->name, cmd);
2952     return -1;
2953     }
2954    
2955     if (h_p == NULL)
2956     *up_p = *parv;
2957     else
2958     {
2959     if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
2960     return -1;
2961    
2962     *up_p = user;
2963     *h_p = host;
2964     }
2965    
2966     parc--;
2967     parv++;
2968    
2969     if (parc != 0)
2970     {
2971     if (irccmp(*parv, "ON") == 0)
2972     {
2973     parc--;
2974     parv++;
2975    
2976     if (target_server == NULL)
2977     {
2978     sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
2979     me.name, source_p->name, cmd);
2980     return -1;
2981     }
2982    
2983 michael 1219 if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
2984 adx 30 {
2985     sendto_one(source_p, form_str(ERR_NOPRIVS),
2986     me.name, source_p->name, "remoteban");
2987     return -1;
2988     }
2989    
2990     if (parc == 0 || EmptyString(*parv))
2991     {
2992     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
2993     me.name, source_p->name, cmd);
2994     return -1;
2995     }
2996    
2997     *target_server = *parv;
2998     parc--;
2999     parv++;
3000     }
3001     else
3002     {
3003     /* Make sure target_server *is* NULL if no ON server found
3004     * caller probably NULL'd it first, but no harm to do it again -db
3005     */
3006     if (target_server != NULL)
3007     *target_server = NULL;
3008     }
3009     }
3010    
3011     if (h_p != NULL)
3012     {
3013     if (strchr(user, '!') != NULL)
3014     {
3015     sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3016     me.name, source_p->name);
3017     return -1;
3018     }
3019    
3020 michael 1243 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 2, *up_p, *h_p))
3021 adx 30 return -1;
3022     }
3023     else
3024 michael 1243 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 1, *up_p))
3025 adx 30 return -1;
3026    
3027     if (reason != NULL)
3028     {
3029 michael 867 if (parc != 0 && !EmptyString(*parv))
3030 adx 30 {
3031     *reason = *parv;
3032 michael 1243 if (!valid_comment(source_p, *reason, 1))
3033 adx 30 return -1;
3034     }
3035     else
3036     *reason = def_reason;
3037     }
3038    
3039     return 1;
3040     }
3041    
3042     /* find_user_host()
3043     *
3044     * inputs - pointer to client placing kline
3045     * - pointer to user_host_or_nick
3046     * - pointer to user buffer
3047     * - pointer to host buffer
3048     * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
3049     * side effects -
3050     */
3051     static int
3052     find_user_host(struct Client *source_p, char *user_host_or_nick,
3053     char *luser, char *lhost, unsigned int flags)
3054     {
3055     struct Client *target_p = NULL;
3056     char *hostp = NULL;
3057    
3058     if (lhost == NULL)
3059     {
3060     strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
3061     return 1;
3062     }
3063    
3064     if ((hostp = strchr(user_host_or_nick, '@')) || *user_host_or_nick == '*')
3065     {
3066     /* Explicit user@host mask given */
3067    
3068 michael 593 if (hostp != NULL) /* I'm a little user@host */
3069 adx 30 {
3070     *(hostp++) = '\0'; /* short and squat */
3071     if (*user_host_or_nick)
3072     strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
3073     else
3074     strcpy(luser, "*");
3075     if (*hostp)
3076     strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
3077     else
3078     strcpy(lhost, "*");
3079     }
3080     else
3081     {
3082     luser[0] = '*'; /* no @ found, assume its *@somehost */
3083     luser[1] = '\0';
3084     strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
3085     }
3086    
3087     return 1;
3088     }
3089 michael 1518 else
3090 adx 30 {
3091     /* Try to find user@host mask from nick */
3092     /* Okay to use source_p as the first param, because source_p == client_p */
3093     if ((target_p =
3094     find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
3095     return 0;
3096    
3097     if (IsExemptKline(target_p))
3098     {
3099     if (!IsServer(source_p))
3100     sendto_one(source_p,
3101     ":%s NOTICE %s :%s is E-lined",
3102     me.name, source_p->name, target_p->name);
3103     return 0;
3104     }
3105    
3106     /*
3107     * turn the "user" bit into "*user", blow away '~'
3108     * if found in original user name (non-idented)
3109     */
3110     strlcpy(luser, target_p->username, USERLEN*4 + 1);
3111    
3112     if (target_p->username[0] == '~')
3113     luser[0] = '*';
3114    
3115     if (target_p->sockhost[0] == '\0' ||
3116     (target_p->sockhost[0] == '0' && target_p->sockhost[1] == '\0'))
3117     strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
3118     else
3119     strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
3120     return 1;
3121     }
3122    
3123     return 0;
3124     }
3125    
3126     /* valid_comment()
3127     *
3128     * inputs - pointer to client
3129     * - pointer to comment
3130     * output - 0 if no valid comment,
3131     * - 1 if valid
3132     * side effects - truncates reason where necessary
3133     */
3134     int
3135     valid_comment(struct Client *source_p, char *comment, int warn)
3136     {
3137     if (strchr(comment, '"'))
3138     {
3139     if (warn)
3140     sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3141     me.name, source_p->name);
3142     return 0;
3143     }
3144    
3145     if (strlen(comment) > REASONLEN)
3146     comment[REASONLEN-1] = '\0';
3147    
3148     return 1;
3149     }
3150    
3151     /* match_conf_password()
3152     *
3153     * inputs - pointer to given password
3154     * - pointer to Conf
3155     * output - 1 or 0 if match
3156     * side effects - none
3157     */
3158     int
3159     match_conf_password(const char *password, const struct AccessItem *aconf)
3160     {
3161     const char *encr = NULL;
3162    
3163 michael 1390 if (EmptyString(password) || EmptyString(aconf->passwd))
3164 adx 30 return 0;
3165    
3166     if (aconf->flags & CONF_FLAGS_ENCRYPTED)
3167 michael 1390 encr = crypt(password, aconf->passwd);
3168 adx 30 else
3169     encr = password;
3170    
3171     return !strcmp(encr, aconf->passwd);
3172     }
3173    
3174     /*
3175     * cluster_a_line
3176     *
3177     * inputs - client sending the cluster
3178     * - command name "KLINE" "XLINE" etc.
3179     * - capab -- CAP_KLN etc. from s_serv.h
3180 michael 1309 * - cluster type -- CLUSTER_KLINE etc. from conf.h
3181 adx 30 * - pattern and args to send along
3182     * output - none
3183     * side effects - Take source_p send the pattern with args given
3184     * along to all servers that match capab and cluster type
3185     */
3186     void
3187     cluster_a_line(struct Client *source_p, const char *command,
3188 michael 593 int capab, int cluster_type, const char *pattern, ...)
3189 adx 30 {
3190     va_list args;
3191     char buffer[IRCD_BUFSIZE];
3192 michael 593 const dlink_node *ptr = NULL;
3193 adx 30
3194     va_start(args, pattern);
3195     vsnprintf(buffer, sizeof(buffer), pattern, args);
3196     va_end(args);
3197    
3198     DLINK_FOREACH(ptr, cluster_items.head)
3199     {
3200 michael 593 const struct ConfItem *conf = ptr->data;
3201 adx 30
3202     if (conf->flags & cluster_type)
3203     sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
3204     "%s %s %s", command, conf->name, buffer);
3205     }
3206     }
3207    
3208     /*
3209     * split_nuh
3210     *
3211     * inputs - pointer to original mask (modified in place)
3212     * - pointer to pointer where nick should go
3213     * - pointer to pointer where user should go
3214     * - pointer to pointer where host should go
3215     * output - NONE
3216     * side effects - mask is modified in place
3217     * If nick pointer is NULL, ignore writing to it
3218     * this allows us to use this function elsewhere.
3219     *
3220     * mask nick user host
3221     * ---------------------- ------- ------- ------
3222     * Dianora!db@db.net Dianora db db.net
3223     * Dianora Dianora * *
3224     * db.net * * db.net
3225     * OR if nick pointer is NULL
3226     * Dianora - * Dianora
3227     * Dianora! Dianora * *
3228     * Dianora!@ Dianora * *
3229     * Dianora!db Dianora db *
3230     * Dianora!@db.net Dianora * db.net
3231     * db@db.net * db db.net
3232     * !@ * * *
3233     * @ * * *
3234     * ! * * *
3235     */
3236     void
3237 michael 593 split_nuh(struct split_nuh_item *const iptr)
3238 adx 30 {
3239     char *p = NULL, *q = NULL;
3240    
3241 michael 593 if (iptr->nickptr)
3242     strlcpy(iptr->nickptr, "*", iptr->nicksize);
3243     if (iptr->userptr)
3244     strlcpy(iptr->userptr, "*", iptr->usersize);
3245     if (iptr->hostptr)
3246     strlcpy(iptr->hostptr, "*", iptr->hostsize);
3247    
3248     if ((p = strchr(iptr->nuhmask, '!')))
3249 adx 30 {
3250     *p = '\0';
3251    
3252 michael 593 if (iptr->nickptr && *iptr->nuhmask != '\0')
3253     strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3254 adx 30
3255 michael 593 if ((q = strchr(++p, '@'))) {
3256     *q++ = '\0';
3257    
3258 adx 30 if (*p != '\0')
3259 michael 593 strlcpy(iptr->userptr, p, iptr->usersize);
3260 adx 30
3261 michael 593 if (*q != '\0')
3262     strlcpy(iptr->hostptr, q, iptr->hostsize);
3263 adx 30 }
3264     else
3265     {
3266     if (*p != '\0')
3267 michael 593 strlcpy(iptr->userptr, p, iptr->usersize);
3268 adx 30 }
3269     }
3270 michael 593 else
3271 adx 30 {
3272 michael 593 /* No ! found so lets look for a user@host */
3273     if ((p = strchr(iptr->nuhmask, '@')))
3274 adx 30 {
3275 michael 593 /* if found a @ */
3276     *p++ = '\0';
3277 adx 30
3278 michael 593 if (*iptr->nuhmask != '\0')
3279     strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
3280 adx 30
3281 michael 593 if (*p != '\0')
3282     strlcpy(iptr->hostptr, p, iptr->hostsize);
3283 adx 30 }
3284 michael 593 else
3285 adx 30 {
3286 michael 593 /* no @ found */
3287     if (!iptr->nickptr || strpbrk(iptr->nuhmask, ".:"))
3288     strlcpy(iptr->hostptr, iptr->nuhmask, iptr->hostsize);
3289 adx 30 else
3290 michael 593 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3291 adx 30 }
3292     }
3293     }
3294    
3295     /*
3296     * flags_to_ascii
3297     *
3298     * inputs - flags is a bitmask
3299     * - pointer to table of ascii letters corresponding
3300     * to each bit
3301     * - flag 1 for convert ToLower if bit missing
3302     * 0 if ignore.
3303     * output - none
3304     * side effects - string pointed to by p has bitmap chars written to it
3305     */
3306     static void
3307     flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3308     int lowerit)
3309     {
3310     unsigned int mask = 1;
3311     int i = 0;
3312    
3313     for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3314     {
3315     if (flags & mask)
3316     *p++ = bit_table[i];
3317 michael 593 else if (lowerit)
3318 adx 30 *p++ = ToLower(bit_table[i]);
3319     }
3320     *p = '\0';
3321     }
3322    
3323     /*
3324     * cidr_limit_reached
3325     *
3326     * inputs - int flag allowing over_rule of limits
3327     * - pointer to the ip to be added
3328     * - pointer to the class
3329     * output - non zero if limit reached
3330     * 0 if limit not reached
3331     * side effects -
3332     */
3333     static int
3334     cidr_limit_reached(int over_rule,
3335     struct irc_ssaddr *ip, struct ClassItem *aclass)
3336     {
3337     dlink_node *ptr = NULL;
3338     struct CidrItem *cidr;
3339    
3340 michael 1377 if (aclass->number_per_cidr <= 0)
3341 adx 30 return 0;
3342    
3343     if (ip->ss.ss_family == AF_INET)
3344     {
3345 michael 1377 if (aclass->cidr_bitlen_ipv4 <= 0)
3346 adx 30 return 0;
3347    
3348     DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3349     {
3350     cidr = ptr->data;
3351 michael 1377 if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3352 adx 30 {
3353 michael 1377 if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3354 adx 30 return -1;
3355     cidr->number_on_this_cidr++;
3356     return 0;
3357     }
3358     }
3359     cidr = MyMalloc(sizeof(struct CidrItem));
3360     cidr->number_on_this_cidr = 1;
3361     cidr->mask = *ip;
3362 michael 1377 mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv4);
3363 adx 30 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3364     }
3365     #ifdef IPV6
3366 michael 1377 else if (aclass->cidr_bitlen_ipv6 > 0)
3367 adx 30 {
3368     DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3369     {
3370     cidr = ptr->data;
3371 michael 1377 if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3372 adx 30 {
3373 michael 1377 if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3374 adx 30 return -1;
3375     cidr->number_on_this_cidr++;
3376     return 0;
3377     }
3378     }
3379     cidr = MyMalloc(sizeof(struct CidrItem));
3380     cidr->number_on_this_cidr = 1;
3381     cidr->mask = *ip;
3382 michael 1377 mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv6);
3383 adx 30 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3384     }
3385     #endif
3386     return 0;
3387     }
3388    
3389     /*
3390     * remove_from_cidr_check
3391     *
3392     * inputs - pointer to the ip to be removed
3393     * - pointer to the class
3394     * output - NONE
3395     * side effects -
3396     */
3397     static void
3398     remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3399     {
3400     dlink_node *ptr = NULL;
3401     dlink_node *next_ptr = NULL;
3402     struct CidrItem *cidr;
3403    
3404 michael 1377 if (aclass->number_per_cidr == 0)
3405 adx 30 return;
3406    
3407     if (ip->ss.ss_family == AF_INET)
3408     {
3409 michael 1377 if (aclass->cidr_bitlen_ipv4 <= 0)
3410 adx 30 return;
3411    
3412     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3413     {
3414     cidr = ptr->data;
3415 michael 1377 if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3416 adx 30 {
3417     cidr->number_on_this_cidr--;
3418     if (cidr->number_on_this_cidr == 0)
3419     {
3420     dlinkDelete(ptr, &aclass->list_ipv4);
3421     MyFree(cidr);
3422     return;
3423     }
3424     }
3425     }
3426     }
3427     #ifdef IPV6
3428 michael 1377 else if (aclass->cidr_bitlen_ipv6 > 0)
3429 adx 30 {
3430     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3431     {
3432     cidr = ptr->data;
3433 michael 1377 if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3434 adx 30 {
3435     cidr->number_on_this_cidr--;
3436     if (cidr->number_on_this_cidr == 0)
3437     {
3438     dlinkDelete(ptr, &aclass->list_ipv6);
3439     MyFree(cidr);
3440     return;
3441     }
3442     }
3443     }
3444     }
3445     #endif
3446     }
3447    
3448     static void
3449     rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3450     dlink_list *old_list, dlink_list *new_list, int changed)
3451     {
3452     dlink_node *ptr;
3453     struct Client *client_p;
3454     struct ConfItem *conf;
3455     struct AccessItem *aconf;
3456    
3457     if (!changed)
3458     {
3459     *new_list = *old_list;
3460     old_list->head = old_list->tail = NULL;
3461     old_list->length = 0;
3462     return;
3463     }
3464    
3465     DLINK_FOREACH(ptr, local_client_list.head)
3466     {
3467     client_p = ptr->data;
3468     if (client_p->localClient->aftype != aftype)
3469     continue;
3470     if (dlink_list_length(&client_p->localClient->confs) == 0)
3471     continue;
3472    
3473     conf = client_p->localClient->confs.tail->data;
3474     if (conf->type == CLIENT_TYPE)
3475     {
3476     aconf = map_to_conf(conf);
3477     if (aconf->class_ptr == oldcl)
3478     cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3479     }
3480     }
3481     }
3482    
3483     /*
3484     * rebuild_cidr_class
3485     *
3486     * inputs - pointer to old conf
3487     * - pointer to new_class
3488     * output - none
3489     * side effects - rebuilds the class link list of cidr blocks
3490     */
3491     void
3492     rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3493     {
3494     struct ClassItem *old_class = map_to_conf(conf);
3495    
3496 michael 1377 if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
3497 adx 30 {
3498 michael 1377 if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
3499 adx 30 rebuild_cidr_list(AF_INET, conf, new_class,
3500     &old_class->list_ipv4, &new_class->list_ipv4,
3501 michael 1377 old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
3502 adx 30
3503     #ifdef IPV6
3504 michael 1377 if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
3505 adx 30 rebuild_cidr_list(AF_INET6, conf, new_class,
3506     &old_class->list_ipv6, &new_class->list_ipv6,
3507 michael 1377 old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
3508 adx 30 #endif
3509     }
3510    
3511     destroy_cidr_class(old_class);
3512     }
3513    
3514     /*
3515     * destroy_cidr_list
3516     *
3517     * inputs - pointer to class dlink list of cidr blocks
3518     * output - none
3519     * side effects - completely destroys the class link list of cidr blocks
3520     */
3521     static void
3522     destroy_cidr_list(dlink_list *list)
3523     {
3524 michael 671 dlink_node *ptr = NULL, *next_ptr = NULL;
3525 adx 30
3526     DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3527     {
3528     dlinkDelete(ptr, list);
3529 michael 671 MyFree(ptr->data);
3530 adx 30 }
3531     }
3532    
3533     /*
3534     * destroy_cidr_class
3535     *
3536     * inputs - pointer to class
3537     * output - none
3538     * side effects - completely destroys the class link list of cidr blocks
3539     */
3540     static void
3541     destroy_cidr_class(struct ClassItem *aclass)
3542     {
3543     destroy_cidr_list(&aclass->list_ipv4);
3544     destroy_cidr_list(&aclass->list_ipv6);
3545     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision