ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1526
Committed: Mon Sep 10 18:06:06 2012 UTC (12 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 92400 byte(s)
Log Message:
- fixed minor compile warnings

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

Properties

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