ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1474
Committed: Sun Jul 22 14:44:07 2012 UTC (13 years, 1 month ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 92455 byte(s)
Log Message:
- removed &localchannels

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

Properties

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