ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1519
Committed: Wed Sep 5 12:02:04 2012 UTC (13 years, 10 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 92464 byte(s)
Log Message:
- Topics as well as user-aways are now sent in a burst by default

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

Properties

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