ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1518
Committed: Sun Sep 2 16:50:40 2012 UTC (12 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 92553 byte(s)
Log Message:
- Removed rkline.conf and rxline.conf leftovers. Regular expression based
  k- and x-lines can be set via ircd.conf only.

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

Properties

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