ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1592
Committed: Sat Oct 27 21:02:32 2012 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 91440 byte(s)
Log Message:
- Second time's the charm? Moving svnroot/ircd-hybrid-8 to
  svnroot/ircd-hybrid/trunk

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

Properties

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