/[svn]/ircd-hybrid-8/src/conf.c
ViewVC logotype

Annotation of /ircd-hybrid-8/src/conf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1377 - (hide annotations)
Mon Apr 30 19:35:16 2012 UTC (8 years, 4 months ago) by michael
File MIME type: text/x-chdr
File size: 95886 byte(s)
- Remove all Class related #defines like MaxTotal, MaxSendq, etc.
  All they do is lead to confusion.

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 hub_items = { NULL, NULL, 0 };
63     dlink_list leaf_items = { NULL, NULL, 0 };
64     dlink_list oconf_items = { NULL, NULL, 0 };
65     dlink_list uconf_items = { NULL, NULL, 0 };
66     dlink_list xconf_items = { NULL, NULL, 0 };
67     dlink_list rxconf_items = { NULL, NULL, 0 };
68     dlink_list rkconf_items = { NULL, NULL, 0 };
69     dlink_list nresv_items = { NULL, NULL, 0 };
70     dlink_list class_items = { NULL, NULL, 0 };
71     dlink_list gdeny_items = { NULL, NULL, 0 };
72    
73     dlink_list temporary_xlines = { NULL, NULL, 0 };
74     dlink_list temporary_resv = { NULL, NULL, 0 };
75    
76     extern unsigned int lineno;
77     extern char linebuf[];
78     extern char conffilebuf[IRCD_BUFSIZE];
79     extern int yyparse(); /* defined in y.tab.c */
80    
81 michael 967 struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
82    
83 adx 30 /* internally defined functions */
84 michael 1325 static void read_conf(FILE *);
85 adx 30 static void clear_out_old_conf(void);
86     static void flush_deleted_I_P(void);
87     static void expire_tklines(dlink_list *);
88     static void garbage_collect_ip_entries(void);
89     static int hash_ip(struct irc_ssaddr *);
90     static int verify_access(struct Client *, const char *);
91     static int attach_iline(struct Client *, struct ConfItem *);
92     static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
93     static void parse_conf_file(int, int);
94     static dlink_list *map_to_list(ConfType);
95     static struct AccessItem *find_regexp_kline(const char *[]);
96     static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
97    
98     /*
99     * bit_len
100     */
101     static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
102     static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
103     static void destroy_cidr_class(struct ClassItem *);
104    
105     static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
106    
107     /* address of default class conf */
108     static struct ConfItem *class_default;
109    
110     /* usually, with hash tables, you use a prime number...
111     * but in this case I am dealing with ip addresses,
112     * not ascii strings.
113     */
114     #define IP_HASH_SIZE 0x1000
115    
116     struct ip_entry
117     {
118     struct irc_ssaddr ip;
119     int count;
120     time_t last_attempt;
121     struct ip_entry *next;
122     };
123    
124     static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
125     static BlockHeap *ip_entry_heap = NULL;
126     static int ip_entries_count = 0;
127    
128    
129 michael 1013 void *
130 adx 30 map_to_conf(struct ConfItem *aconf)
131     {
132     void *conf;
133 michael 1013 conf = (void *)((uintptr_t)aconf +
134     (uintptr_t)sizeof(struct ConfItem));
135 adx 30 return(conf);
136     }
137    
138 michael 1013 struct ConfItem *
139 adx 30 unmap_conf_item(void *aconf)
140     {
141     struct ConfItem *conf;
142    
143 michael 1013 conf = (struct ConfItem *)((uintptr_t)aconf -
144     (uintptr_t)sizeof(struct ConfItem));
145 adx 30 return(conf);
146     }
147    
148     /* conf_dns_callback()
149     *
150     * inputs - pointer to struct AccessItem
151     * - pointer to DNSReply reply
152     * output - none
153     * side effects - called when resolver query finishes
154     * if the query resulted in a successful search, hp will contain
155     * a non-null pointer, otherwise hp will be null.
156     * if successful save hp in the conf item it was called with
157     */
158     static void
159 michael 992 conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
160 adx 30 {
161 michael 1005 struct AccessItem *aconf = vptr;
162 adx 30
163 michael 992 aconf->dns_pending = 0;
164 adx 30
165 michael 992 if (addr != NULL)
166     memcpy(&aconf->ipnum, addr, sizeof(aconf->ipnum));
167     else
168     aconf->dns_failed = 1;
169 adx 30 }
170    
171     /* conf_dns_lookup()
172     *
173     * do a nameserver lookup of the conf host
174     * if the conf entry is currently doing a ns lookup do nothing, otherwise
175     * allocate a dns_query and start ns lookup.
176     */
177     static void
178     conf_dns_lookup(struct AccessItem *aconf)
179     {
180 michael 992 if (!aconf->dns_pending)
181 adx 30 {
182 michael 992 aconf->dns_pending = 1;
183     gethost_byname(conf_dns_callback, aconf, aconf->host);
184 adx 30 }
185     }
186    
187     /* make_conf_item()
188     *
189     * inputs - type of item
190     * output - pointer to new conf entry
191     * side effects - none
192     */
193     struct ConfItem *
194     make_conf_item(ConfType type)
195     {
196     struct ConfItem *conf = NULL;
197     struct AccessItem *aconf = NULL;
198     struct ClassItem *aclass = NULL;
199     int status = 0;
200    
201     switch (type)
202     {
203     case DLINE_TYPE:
204     case EXEMPTDLINE_TYPE:
205     case GLINE_TYPE:
206     case KLINE_TYPE:
207     case CLIENT_TYPE:
208     case OPER_TYPE:
209     case SERVER_TYPE:
210     conf = MyMalloc(sizeof(struct ConfItem) +
211     sizeof(struct AccessItem));
212     aconf = map_to_conf(conf);
213     aconf->aftype = AF_INET;
214    
215     /* Yes, sigh. switch on type again */
216     switch (type)
217     {
218     case EXEMPTDLINE_TYPE:
219     status = CONF_EXEMPTDLINE;
220     break;
221    
222     case DLINE_TYPE:
223     status = CONF_DLINE;
224     break;
225    
226     case KLINE_TYPE:
227     status = CONF_KLINE;
228     break;
229    
230     case GLINE_TYPE:
231     status = CONF_GLINE;
232     break;
233    
234     case CLIENT_TYPE:
235     status = CONF_CLIENT;
236     break;
237    
238     case OPER_TYPE:
239     status = CONF_OPERATOR;
240     dlinkAdd(conf, &conf->node, &oconf_items);
241     break;
242    
243     case SERVER_TYPE:
244     status = CONF_SERVER;
245     dlinkAdd(conf, &conf->node, &server_items);
246     break;
247    
248     default:
249     break;
250     }
251     aconf->status = status;
252     break;
253    
254     case LEAF_TYPE:
255     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
256     sizeof(struct MatchItem));
257     dlinkAdd(conf, &conf->node, &leaf_items);
258     break;
259    
260     case HUB_TYPE:
261     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
262     sizeof(struct MatchItem));
263     dlinkAdd(conf, &conf->node, &hub_items);
264     break;
265    
266     case ULINE_TYPE:
267     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
268     sizeof(struct MatchItem));
269     dlinkAdd(conf, &conf->node, &uconf_items);
270     break;
271    
272     case GDENY_TYPE:
273     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
274     sizeof(struct AccessItem));
275 michael 102 dlinkAdd(conf, &conf->node, &gdeny_items);
276 adx 30 break;
277    
278     case XLINE_TYPE:
279     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
280     sizeof(struct MatchItem));
281     dlinkAdd(conf, &conf->node, &xconf_items);
282     break;
283 michael 1009 #ifdef HAVE_LIBPCRE
284 adx 30 case RXLINE_TYPE:
285     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
286     sizeof(struct MatchItem));
287     dlinkAdd(conf, &conf->node, &rxconf_items);
288     break;
289    
290     case RKLINE_TYPE:
291     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
292     sizeof(struct AccessItem));
293     aconf = map_to_conf(conf);
294     aconf->status = CONF_KLINE;
295     dlinkAdd(conf, &conf->node, &rkconf_items);
296     break;
297 michael 1009 #endif
298 adx 30 case CLUSTER_TYPE:
299     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
300     dlinkAdd(conf, &conf->node, &cluster_items);
301     break;
302    
303     case CRESV_TYPE:
304     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
305     sizeof(struct ResvChannel));
306     break;
307    
308     case NRESV_TYPE:
309     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
310     sizeof(struct MatchItem));
311     dlinkAdd(conf, &conf->node, &nresv_items);
312     break;
313    
314 michael 1157 case SERVICE_TYPE:
315     status = CONF_SERVICE;
316     conf = MyMalloc(sizeof(struct ConfItem));
317     dlinkAdd(conf, &conf->node, &service_items);
318     break;
319    
320 adx 30 case CLASS_TYPE:
321 michael 671 conf = MyMalloc(sizeof(struct ConfItem) +
322     sizeof(struct ClassItem));
323 adx 30 dlinkAdd(conf, &conf->node, &class_items);
324 michael 671
325     aclass = map_to_conf(conf);
326     aclass->active = 1;
327 michael 1377 aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
328     aclass->ping_freq = DEFAULT_PINGFREQUENCY;
329     aclass->max_total = MAXIMUM_LINKS_DEFAULT;
330     aclass->max_sendq = DEFAULT_SENDQ;
331 michael 671
332 adx 30 break;
333    
334     default:
335     conf = NULL;
336     break;
337     }
338    
339     /* XXX Yes, this will core if default is hit. I want it to for now - db */
340     conf->type = type;
341    
342 michael 671 return conf;
343 adx 30 }
344    
345     void
346     delete_conf_item(struct ConfItem *conf)
347     {
348 michael 433 dlink_node *m = NULL;
349 adx 30 struct MatchItem *match_item;
350     struct AccessItem *aconf;
351     ConfType type = conf->type;
352    
353     MyFree(conf->name);
354     conf->name = NULL;
355    
356     switch(type)
357     {
358     case DLINE_TYPE:
359     case EXEMPTDLINE_TYPE:
360     case GLINE_TYPE:
361     case KLINE_TYPE:
362     case CLIENT_TYPE:
363     case OPER_TYPE:
364     case SERVER_TYPE:
365     aconf = map_to_conf(conf);
366    
367 michael 992 if (aconf->dns_pending)
368     delete_resolver_queries(aconf);
369 adx 30 if (aconf->passwd != NULL)
370     memset(aconf->passwd, 0, strlen(aconf->passwd));
371     if (aconf->spasswd != NULL)
372     memset(aconf->spasswd, 0, strlen(aconf->spasswd));
373     aconf->class_ptr = NULL;
374    
375     MyFree(aconf->passwd);
376     MyFree(aconf->spasswd);
377     MyFree(aconf->reason);
378     MyFree(aconf->oper_reason);
379     MyFree(aconf->user);
380     MyFree(aconf->host);
381 michael 1306 MyFree(aconf->cipher_list);
382 adx 30 #ifdef HAVE_LIBCRYPTO
383     if (aconf->rsa_public_key)
384     RSA_free(aconf->rsa_public_key);
385     MyFree(aconf->rsa_public_key_file);
386     #endif
387    
388     /* Yes, sigh. switch on type again */
389     switch(type)
390     {
391     case EXEMPTDLINE_TYPE:
392     case DLINE_TYPE:
393     case GLINE_TYPE:
394     case KLINE_TYPE:
395     case CLIENT_TYPE:
396     MyFree(conf);
397     break;
398    
399     case OPER_TYPE:
400     aconf = map_to_conf(conf);
401     if (!IsConfIllegal(aconf))
402     dlinkDelete(&conf->node, &oconf_items);
403     MyFree(conf);
404     break;
405    
406     case SERVER_TYPE:
407     aconf = map_to_conf(conf);
408     if (!IsConfIllegal(aconf))
409     dlinkDelete(&conf->node, &server_items);
410     MyFree(conf);
411     break;
412    
413     default:
414     break;
415     }
416     break;
417    
418     case HUB_TYPE:
419     match_item = map_to_conf(conf);
420     MyFree(match_item->user);
421     MyFree(match_item->host);
422     MyFree(match_item->reason);
423     MyFree(match_item->oper_reason);
424     /* If marked illegal, its already been pulled off of the hub_items list */
425     if (!match_item->illegal)
426     dlinkDelete(&conf->node, &hub_items);
427     MyFree(conf);
428     break;
429    
430     case LEAF_TYPE:
431     match_item = map_to_conf(conf);
432     MyFree(match_item->user);
433     MyFree(match_item->host);
434     MyFree(match_item->reason);
435     MyFree(match_item->oper_reason);
436     /* If marked illegal, its already been pulled off of the leaf_items list */
437     if (!match_item->illegal)
438     dlinkDelete(&conf->node, &leaf_items);
439     MyFree(conf);
440     break;
441    
442     case ULINE_TYPE:
443     match_item = map_to_conf(conf);
444     MyFree(match_item->user);
445     MyFree(match_item->host);
446     MyFree(match_item->reason);
447     MyFree(match_item->oper_reason);
448     dlinkDelete(&conf->node, &uconf_items);
449     MyFree(conf);
450     break;
451    
452     case XLINE_TYPE:
453     match_item = map_to_conf(conf);
454     MyFree(match_item->user);
455     MyFree(match_item->host);
456     MyFree(match_item->reason);
457     MyFree(match_item->oper_reason);
458     dlinkDelete(&conf->node, &xconf_items);
459     MyFree(conf);
460     break;
461 michael 1009 #ifdef HAVE_LIBPCRE
462 adx 30 case RKLINE_TYPE:
463     aconf = map_to_conf(conf);
464     MyFree(aconf->regexuser);
465     MyFree(aconf->regexhost);
466     MyFree(aconf->user);
467     MyFree(aconf->host);
468     MyFree(aconf->reason);
469     MyFree(aconf->oper_reason);
470     dlinkDelete(&conf->node, &rkconf_items);
471     MyFree(conf);
472     break;
473    
474     case RXLINE_TYPE:
475     MyFree(conf->regexpname);
476     match_item = map_to_conf(conf);
477     MyFree(match_item->user);
478     MyFree(match_item->host);
479     MyFree(match_item->reason);
480     MyFree(match_item->oper_reason);
481     dlinkDelete(&conf->node, &rxconf_items);
482     MyFree(conf);
483     break;
484 michael 1009 #endif
485 adx 30 case NRESV_TYPE:
486     match_item = map_to_conf(conf);
487     MyFree(match_item->user);
488     MyFree(match_item->host);
489     MyFree(match_item->reason);
490     MyFree(match_item->oper_reason);
491     dlinkDelete(&conf->node, &nresv_items);
492 michael 433
493     if (conf->flags & CONF_FLAGS_TEMPORARY)
494     if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
495     free_dlink_node(m);
496    
497 adx 30 MyFree(conf);
498     break;
499    
500     case GDENY_TYPE:
501     aconf = map_to_conf(conf);
502     MyFree(aconf->user);
503     MyFree(aconf->host);
504     dlinkDelete(&conf->node, &gdeny_items);
505     MyFree(conf);
506     break;
507    
508     case CLUSTER_TYPE:
509     dlinkDelete(&conf->node, &cluster_items);
510     MyFree(conf);
511     break;
512    
513     case CRESV_TYPE:
514 michael 433 if (conf->flags & CONF_FLAGS_TEMPORARY)
515     if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
516     free_dlink_node(m);
517    
518 adx 30 MyFree(conf);
519     break;
520    
521     case CLASS_TYPE:
522     dlinkDelete(&conf->node, &class_items);
523     MyFree(conf);
524     break;
525    
526 michael 1157 case SERVICE_TYPE:
527     dlinkDelete(&conf->node, &service_items);
528     MyFree(conf);
529     break;
530    
531 adx 30 default:
532     break;
533     }
534     }
535    
536     /* free_access_item()
537     *
538     * inputs - pointer to conf to free
539     * output - none
540     * side effects - crucial password fields are zeroed, conf is freed
541     */
542     void
543     free_access_item(struct AccessItem *aconf)
544     {
545     struct ConfItem *conf;
546    
547     if (aconf == NULL)
548     return;
549     conf = unmap_conf_item(aconf);
550     delete_conf_item(conf);
551     }
552    
553     static const unsigned int shared_bit_table[] =
554     { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
555    
556     /* report_confitem_types()
557     *
558     * inputs - pointer to client requesting confitem report
559     * - ConfType to report
560     * output - none
561     * side effects -
562     */
563     void
564 michael 1368 report_confitem_types(struct Client *source_p, ConfType type)
565 adx 30 {
566     dlink_node *ptr = NULL;
567     struct ConfItem *conf = NULL;
568     struct AccessItem *aconf = NULL;
569     struct MatchItem *matchitem = NULL;
570     struct ClassItem *classitem = NULL;
571     char buf[12];
572     char *p = NULL;
573    
574     switch (type)
575     {
576     case GDENY_TYPE:
577     DLINK_FOREACH(ptr, gdeny_items.head)
578     {
579     conf = ptr->data;
580     aconf = map_to_conf(conf);
581    
582     p = buf;
583    
584     if (aconf->flags & GDENY_BLOCK)
585     *p++ = 'B';
586     else
587     *p++ = 'b';
588    
589     if (aconf->flags & GDENY_REJECT)
590     *p++ = 'R';
591     else
592     *p++ = 'r';
593    
594     *p = '\0';
595    
596     sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
597     me.name, RPL_STATSDEBUG, source_p->name,
598     aconf->user, aconf->host, conf->name, buf);
599     }
600     break;
601    
602     case XLINE_TYPE:
603     DLINK_FOREACH(ptr, xconf_items.head)
604     {
605     conf = ptr->data;
606     matchitem = map_to_conf(conf);
607    
608     sendto_one(source_p, form_str(RPL_STATSXLINE),
609     me.name, source_p->name,
610     matchitem->hold ? "x": "X", matchitem->count,
611     conf->name, matchitem->reason);
612     }
613     break;
614    
615 michael 1009 #ifdef HAVE_LIBPCRE
616 adx 30 case RXLINE_TYPE:
617     DLINK_FOREACH(ptr, rxconf_items.head)
618     {
619     conf = ptr->data;
620     matchitem = map_to_conf(conf);
621    
622     sendto_one(source_p, form_str(RPL_STATSXLINE),
623     me.name, source_p->name,
624 michael 1368 "XR", matchitem->count,
625 adx 30 conf->name, matchitem->reason);
626     }
627     break;
628    
629     case RKLINE_TYPE:
630     DLINK_FOREACH(ptr, rkconf_items.head)
631     {
632     aconf = map_to_conf((conf = ptr->data));
633    
634     sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
635 michael 1368 source_p->name, "KR", aconf->host, aconf->user,
636 adx 30 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
637     }
638     break;
639 michael 1009 #endif
640 adx 30
641     case ULINE_TYPE:
642     DLINK_FOREACH(ptr, uconf_items.head)
643     {
644     conf = ptr->data;
645     matchitem = map_to_conf(conf);
646    
647     p = buf;
648    
649     /* some of these are redundant for the sake of
650     * consistency with cluster{} flags
651     */
652     *p++ = 'c';
653     flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
654    
655     sendto_one(source_p, form_str(RPL_STATSULINE),
656     me.name, source_p->name, conf->name,
657     matchitem->user?matchitem->user: "*",
658     matchitem->host?matchitem->host: "*", buf);
659     }
660    
661     DLINK_FOREACH(ptr, cluster_items.head)
662     {
663     conf = ptr->data;
664    
665     p = buf;
666    
667     *p++ = 'C';
668     flags_to_ascii(conf->flags, shared_bit_table, p, 0);
669    
670     sendto_one(source_p, form_str(RPL_STATSULINE),
671     me.name, source_p->name, conf->name,
672     "*", "*", buf);
673     }
674    
675     break;
676    
677     case OPER_TYPE:
678     DLINK_FOREACH(ptr, oconf_items.head)
679     {
680     conf = ptr->data;
681     aconf = map_to_conf(conf);
682    
683     /* Don't allow non opers to see oper privs */
684 michael 1219 if (HasUMode(source_p, UMODE_OPER))
685 adx 30 sendto_one(source_p, form_str(RPL_STATSOLINE),
686     me.name, source_p->name, 'O', aconf->user, aconf->host,
687     conf->name, oper_privs_as_string(aconf->port),
688     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
689     else
690     sendto_one(source_p, form_str(RPL_STATSOLINE),
691     me.name, source_p->name, 'O', aconf->user, aconf->host,
692     conf->name, "0",
693     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
694     }
695     break;
696    
697     case CLASS_TYPE:
698     DLINK_FOREACH(ptr, class_items.head)
699     {
700     conf = ptr->data;
701     classitem = map_to_conf(conf);
702     sendto_one(source_p, form_str(RPL_STATSYLINE),
703     me.name, source_p->name, 'Y',
704 michael 1377 conf->name, classitem->ping_freq,
705     classitem->con_freq,
706     classitem->max_total, classitem->max_sendq,
707     classitem->curr_user_count,
708 michael 671 classitem->active ? "active" : "disabled");
709 adx 30 }
710     break;
711    
712     case CONF_TYPE:
713     case CLIENT_TYPE:
714     break;
715    
716 michael 1175 case SERVICE_TYPE:
717 michael 1157 DLINK_FOREACH(ptr, service_items.head)
718     {
719     conf = ptr->data;
720 michael 1175 sendto_one(source_p, form_str(RPL_STATSSERVICE),
721     me.name, source_p->name, 'S', "*", conf->name, 0, 0);
722 michael 1157 }
723     break;
724    
725 adx 30 case SERVER_TYPE:
726     DLINK_FOREACH(ptr, server_items.head)
727     {
728     p = buf;
729    
730     conf = ptr->data;
731     aconf = map_to_conf(conf);
732    
733     buf[0] = '\0';
734    
735     if (IsConfAllowAutoConn(aconf))
736     *p++ = 'A';
737 michael 1303 if (IsConfSSL(aconf))
738     *p++ = 'S';
739 adx 30 if (IsConfTopicBurst(aconf))
740     *p++ = 'T';
741     if (buf[0] == '\0')
742     *p++ = '*';
743    
744     *p = '\0';
745    
746 michael 671 /*
747     * Allow admins to see actual ips unless hide_server_ips is enabled
748 adx 30 */
749 michael 1219 if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
750 adx 30 sendto_one(source_p, form_str(RPL_STATSCLINE),
751     me.name, source_p->name, 'C', aconf->host,
752     buf, conf->name, aconf->port,
753     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
754     else
755     sendto_one(source_p, form_str(RPL_STATSCLINE),
756     me.name, source_p->name, 'C',
757     "*@127.0.0.1", buf, conf->name, aconf->port,
758     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
759     }
760     break;
761    
762     case HUB_TYPE:
763     DLINK_FOREACH(ptr, hub_items.head)
764     {
765     conf = ptr->data;
766     matchitem = map_to_conf(conf);
767     sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
768     source_p->name, 'H', matchitem->host, conf->name, 0, "*");
769     }
770     break;
771    
772     case LEAF_TYPE:
773     DLINK_FOREACH(ptr, leaf_items.head)
774     {
775     conf = ptr->data;
776     matchitem = map_to_conf(conf);
777     sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
778     source_p->name, 'L', matchitem->host, conf->name, 0, "*");
779     }
780     break;
781    
782     case GLINE_TYPE:
783     case KLINE_TYPE:
784     case DLINE_TYPE:
785     case EXEMPTDLINE_TYPE:
786     case CRESV_TYPE:
787     case NRESV_TYPE:
788     case CLUSTER_TYPE:
789 michael 1009 default:
790 adx 30 break;
791     }
792     }
793    
794     /* check_client()
795     *
796     * inputs - pointer to client
797     * output - 0 = Success
798     * NOT_AUTHORIZED (-1) = Access denied (no I line match)
799     * IRCD_SOCKET_ERROR (-2) = Bad socket.
800     * I_LINE_FULL (-3) = I-line is full
801     * TOO_MANY (-4) = Too many connections from hostname
802     * BANNED_CLIENT (-5) = K-lined
803     * side effects - Ordinary client access check.
804     * Look for conf lines which have the same
805     * status as the flags passed.
806     */
807     static void *
808     check_client(va_list args)
809     {
810     struct Client *source_p = va_arg(args, struct Client *);
811     const char *username = va_arg(args, const char *);
812     int i;
813    
814     /* I'm already in big trouble if source_p->localClient is NULL -db */
815     if ((i = verify_access(source_p, username)))
816 michael 1247 ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
817 adx 30 source_p->name, source_p->sockhost);
818    
819     switch (i)
820     {
821     case TOO_MANY:
822     sendto_realops_flags(UMODE_FULL, L_ALL,
823     "Too many on IP for %s (%s).",
824     get_client_name(source_p, SHOW_IP),
825     source_p->sockhost);
826 michael 1247 ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
827 adx 30 get_client_name(source_p, SHOW_IP));
828 michael 896 ++ServerStats.is_ref;
829 adx 30 exit_client(source_p, &me, "No more connections allowed on that IP");
830     break;
831    
832     case I_LINE_FULL:
833     sendto_realops_flags(UMODE_FULL, L_ALL,
834     "I-line is full for %s (%s).",
835     get_client_name(source_p, SHOW_IP),
836     source_p->sockhost);
837 michael 1247 ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
838 adx 30 get_client_name(source_p, SHOW_IP));
839 michael 896 ++ServerStats.is_ref;
840 adx 30 exit_client(source_p, &me,
841     "No more connections allowed in your connection class");
842     break;
843    
844     case NOT_AUTHORIZED:
845 michael 896 ++ServerStats.is_ref;
846 adx 30 /* jdc - lists server name & port connections are on */
847     /* a purely cosmetical change */
848     sendto_realops_flags(UMODE_UNAUTH, L_ALL,
849     "Unauthorized client connection from %s [%s] on [%s/%u].",
850     get_client_name(source_p, SHOW_IP),
851 michael 891 source_p->sockhost,
852 adx 30 source_p->localClient->listener->name,
853     source_p->localClient->listener->port);
854 michael 1247 ilog(LOG_TYPE_IRCD,
855 adx 30 "Unauthorized client connection from %s on [%s/%u].",
856     get_client_name(source_p, SHOW_IP),
857     source_p->localClient->listener->name,
858     source_p->localClient->listener->port);
859    
860     /* XXX It is prolematical whether it is better to use the
861     * capture reject code here or rely on the connecting too fast code.
862     * - Dianora
863     */
864 michael 671 if (REJECT_HOLD_TIME > 0)
865 adx 30 {
866     sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
867     me.name, source_p->name);
868     source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
869     SetCaptured(source_p);
870     }
871     else
872     exit_client(source_p, &me, "You are not authorized to use this server");
873     break;
874 michael 891
875 adx 30 case BANNED_CLIENT:
876     /*
877     * Don't exit them immediately, play with them a bit.
878     * - Dianora
879     */
880     if (REJECT_HOLD_TIME > 0)
881     {
882     source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
883     SetCaptured(source_p);
884     }
885     else
886     exit_client(source_p, &me, "Banned");
887 michael 896 ++ServerStats.is_ref;
888 adx 30 break;
889    
890     case 0:
891     default:
892     break;
893     }
894    
895     return (i < 0 ? NULL : source_p);
896     }
897    
898     /* verify_access()
899     *
900     * inputs - pointer to client to verify
901     * - pointer to proposed username
902     * output - 0 if success -'ve if not
903     * side effect - find the first (best) I line to attach.
904     */
905     static int
906     verify_access(struct Client *client_p, const char *username)
907     {
908     struct AccessItem *aconf = NULL, *rkconf = NULL;
909     struct ConfItem *conf = NULL;
910     char non_ident[USERLEN + 1] = { '~', '\0' };
911     const char *uhi[3];
912    
913     if (IsGotId(client_p))
914     {
915     aconf = find_address_conf(client_p->host, client_p->username,
916     &client_p->localClient->ip,
917     client_p->localClient->aftype,
918     client_p->localClient->passwd);
919     }
920     else
921     {
922     strlcpy(non_ident+1, username, sizeof(non_ident)-1);
923     aconf = find_address_conf(client_p->host,non_ident,
924     &client_p->localClient->ip,
925     client_p->localClient->aftype,
926     client_p->localClient->passwd);
927     }
928    
929     uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
930     uhi[1] = client_p->host;
931     uhi[2] = client_p->sockhost;
932    
933     rkconf = find_regexp_kline(uhi);
934    
935     if (aconf != NULL)
936     {
937     if (IsConfClient(aconf) && !rkconf)
938     {
939     conf = unmap_conf_item(aconf);
940    
941     if (IsConfRedir(aconf))
942     {
943     sendto_one(client_p, form_str(RPL_REDIR),
944     me.name, client_p->name,
945     conf->name ? conf->name : "",
946     aconf->port);
947     return(NOT_AUTHORIZED);
948     }
949    
950     if (IsConfDoIdentd(aconf))
951     SetNeedId(client_p);
952    
953     /* Thanks for spoof idea amm */
954     if (IsConfDoSpoofIp(aconf))
955     {
956     conf = unmap_conf_item(aconf);
957    
958     if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
959     sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
960     client_p->name, client_p->host, conf->name);
961     strlcpy(client_p->host, conf->name, sizeof(client_p->host));
962     SetIPSpoof(client_p);
963     }
964    
965     return(attach_iline(client_p, conf));
966     }
967     else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
968     {
969     /* XXX */
970     aconf = rkconf ? rkconf : aconf;
971     if (IsConfGline(aconf))
972     sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
973     client_p->name);
974     if (ConfigFileEntry.kline_with_reason)
975     sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
976     me.name, client_p->name, aconf->reason);
977     return(BANNED_CLIENT);
978     }
979     }
980    
981     return(NOT_AUTHORIZED);
982     }
983    
984     /* attach_iline()
985     *
986     * inputs - client pointer
987     * - conf pointer
988     * output -
989     * side effects - do actual attach
990     */
991     static int
992     attach_iline(struct Client *client_p, struct ConfItem *conf)
993     {
994     struct AccessItem *aconf;
995     struct ClassItem *aclass;
996     struct ip_entry *ip_found;
997     int a_limit_reached = 0;
998     int local = 0, global = 0, ident = 0;
999    
1000     ip_found = find_or_add_ip(&client_p->localClient->ip);
1001     ip_found->count++;
1002     SetIpHash(client_p);
1003    
1004 michael 624 aconf = map_to_conf(conf);
1005 adx 30 if (aconf->class_ptr == NULL)
1006     return NOT_AUTHORIZED; /* If class is missing, this is best */
1007    
1008 michael 624 aclass = map_to_conf(aconf->class_ptr);
1009 adx 30
1010     count_user_host(client_p->username, client_p->host,
1011     &global, &local, &ident);
1012    
1013     /* XXX blah. go down checking the various silly limits
1014     * setting a_limit_reached if any limit is reached.
1015     * - Dianora
1016     */
1017 michael 1377 if (aclass->max_total != 0 && aclass->curr_user_count >= aclass->max_total)
1018 adx 30 a_limit_reached = 1;
1019 michael 1377 else if (aclass->max_perip != 0 && ip_found->count > aclass->max_perip)
1020 adx 30 a_limit_reached = 1;
1021 michael 1377 else if (aclass->max_local != 0 && local >= aclass->max_local)
1022 adx 30 a_limit_reached = 1;
1023 michael 1377 else if (aclass->max_global != 0 && global >= aclass->max_global)
1024 adx 30 a_limit_reached = 1;
1025 michael 1377 else if (aclass->max_ident != 0 && ident >= aclass->max_ident &&
1026 adx 30 client_p->username[0] != '~')
1027     a_limit_reached = 1;
1028    
1029     if (a_limit_reached)
1030     {
1031     if (!IsConfExemptLimits(aconf))
1032 michael 624 return TOO_MANY; /* Already at maximum allowed */
1033 adx 30
1034     sendto_one(client_p,
1035     ":%s NOTICE %s :*** Your connection class is full, "
1036     "but you have exceed_limit = yes;", me.name, client_p->name);
1037     }
1038    
1039     return attach_conf(client_p, conf);
1040     }
1041    
1042     /* init_ip_hash_table()
1043     *
1044     * inputs - NONE
1045     * output - NONE
1046     * side effects - allocate memory for ip_entry(s)
1047     * - clear the ip hash table
1048     */
1049     void
1050     init_ip_hash_table(void)
1051     {
1052     ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
1053     2 * hard_fdlimit);
1054     memset(ip_hash_table, 0, sizeof(ip_hash_table));
1055     }
1056    
1057     /* find_or_add_ip()
1058     *
1059     * inputs - pointer to struct irc_ssaddr
1060     * output - pointer to a struct ip_entry
1061     * side effects -
1062     *
1063     * If the ip # was not found, a new struct ip_entry is created, and the ip
1064     * count set to 0.
1065     */
1066     static struct ip_entry *
1067     find_or_add_ip(struct irc_ssaddr *ip_in)
1068     {
1069     struct ip_entry *ptr, *newptr;
1070     int hash_index = hash_ip(ip_in), res;
1071     struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1072     #ifdef IPV6
1073     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1074     #endif
1075    
1076     for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1077     {
1078     #ifdef IPV6
1079     if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1080     continue;
1081     if (ip_in->ss.ss_family == AF_INET6)
1082     {
1083     ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1084     res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1085     }
1086     else
1087     #endif
1088     {
1089     ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1090     res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1091     }
1092     if (res == 0)
1093     {
1094     /* Found entry already in hash, return it. */
1095     return ptr;
1096     }
1097     }
1098    
1099     if (ip_entries_count >= 2 * hard_fdlimit)
1100     garbage_collect_ip_entries();
1101    
1102     newptr = BlockHeapAlloc(ip_entry_heap);
1103     ip_entries_count++;
1104     memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
1105    
1106     newptr->next = ip_hash_table[hash_index];
1107     ip_hash_table[hash_index] = newptr;
1108    
1109     return newptr;
1110     }
1111    
1112     /* remove_one_ip()
1113     *
1114     * inputs - unsigned long IP address value
1115     * output - NONE
1116     * side effects - The ip address given, is looked up in ip hash table
1117     * and number of ip#'s for that ip decremented.
1118     * If ip # count reaches 0 and has expired,
1119     * the struct ip_entry is returned to the ip_entry_heap
1120     */
1121     void
1122     remove_one_ip(struct irc_ssaddr *ip_in)
1123     {
1124     struct ip_entry *ptr;
1125     struct ip_entry *last_ptr = NULL;
1126     int hash_index = hash_ip(ip_in), res;
1127     struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1128     #ifdef IPV6
1129     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1130     #endif
1131    
1132     for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1133     {
1134     #ifdef IPV6
1135     if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1136     continue;
1137     if (ip_in->ss.ss_family == AF_INET6)
1138     {
1139     ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1140     res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1141     }
1142     else
1143     #endif
1144     {
1145     ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1146     res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1147     }
1148     if (res)
1149     continue;
1150     if (ptr->count > 0)
1151     ptr->count--;
1152     if (ptr->count == 0 &&
1153     (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1154     {
1155     if (last_ptr != NULL)
1156     last_ptr->next = ptr->next;
1157     else
1158     ip_hash_table[hash_index] = ptr->next;
1159    
1160     BlockHeapFree(ip_entry_heap, ptr);
1161     ip_entries_count--;
1162     return;
1163     }
1164     last_ptr = ptr;
1165     }
1166     }
1167    
1168     /* hash_ip()
1169     *
1170     * input - pointer to an irc_inaddr
1171     * output - integer value used as index into hash table
1172     * side effects - hopefully, none
1173     */
1174     static int
1175     hash_ip(struct irc_ssaddr *addr)
1176     {
1177     if (addr->ss.ss_family == AF_INET)
1178     {
1179     struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
1180     int hash;
1181 michael 1032 uint32_t ip;
1182 adx 30
1183     ip = ntohl(v4->sin_addr.s_addr);
1184     hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
1185     return hash;
1186     }
1187     #ifdef IPV6
1188     else
1189     {
1190     int hash;
1191     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
1192 michael 1032 uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
1193 adx 30
1194     hash = ip[0] ^ ip[3];
1195     hash ^= hash >> 16;
1196     hash ^= hash >> 8;
1197     hash = hash & (IP_HASH_SIZE - 1);
1198     return hash;
1199     }
1200     #else
1201     return 0;
1202     #endif
1203     }
1204    
1205     /* count_ip_hash()
1206     *
1207     * inputs - pointer to counter of number of ips hashed
1208     * - pointer to memory used for ip hash
1209     * output - returned via pointers input
1210     * side effects - NONE
1211     *
1212     * number of hashed ip #'s is counted up, plus the amount of memory
1213     * used in the hash.
1214     */
1215     void
1216 michael 948 count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
1217 adx 30 {
1218     struct ip_entry *ptr;
1219     int i;
1220    
1221     *number_ips_stored = 0;
1222     *mem_ips_stored = 0;
1223    
1224     for (i = 0; i < IP_HASH_SIZE; i++)
1225     {
1226     for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
1227     {
1228     *number_ips_stored += 1;
1229     *mem_ips_stored += sizeof(struct ip_entry);
1230     }
1231     }
1232     }
1233    
1234     /* garbage_collect_ip_entries()
1235     *
1236     * input - NONE
1237     * output - NONE
1238     * side effects - free up all ip entries with no connections
1239     */
1240     static void
1241     garbage_collect_ip_entries(void)
1242     {
1243     struct ip_entry *ptr;
1244     struct ip_entry *last_ptr;
1245     struct ip_entry *next_ptr;
1246     int i;
1247    
1248     for (i = 0; i < IP_HASH_SIZE; i++)
1249     {
1250     last_ptr = NULL;
1251    
1252     for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
1253     {
1254     next_ptr = ptr->next;
1255    
1256     if (ptr->count == 0 &&
1257     (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1258     {
1259     if (last_ptr != NULL)
1260     last_ptr->next = ptr->next;
1261     else
1262     ip_hash_table[i] = ptr->next;
1263     BlockHeapFree(ip_entry_heap, ptr);
1264     ip_entries_count--;
1265     }
1266     else
1267     last_ptr = ptr;
1268     }
1269     }
1270     }
1271    
1272     /* detach_conf()
1273     *
1274     * inputs - pointer to client to detach
1275     * - type of conf to detach
1276     * output - 0 for success, -1 for failure
1277     * side effects - Disassociate configuration from the client.
1278     * Also removes a class from the list if marked for deleting.
1279     */
1280     int
1281     detach_conf(struct Client *client_p, ConfType type)
1282     {
1283     dlink_node *ptr, *next_ptr;
1284     struct ConfItem *conf;
1285     struct ClassItem *aclass;
1286     struct AccessItem *aconf;
1287     struct ConfItem *aclass_conf;
1288     struct MatchItem *match_item;
1289    
1290     DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
1291     {
1292     conf = ptr->data;
1293    
1294     if (type == CONF_TYPE || conf->type == type)
1295     {
1296     dlinkDelete(ptr, &client_p->localClient->confs);
1297     free_dlink_node(ptr);
1298    
1299     switch (conf->type)
1300     {
1301     case CLIENT_TYPE:
1302     case OPER_TYPE:
1303     case SERVER_TYPE:
1304 michael 618 aconf = map_to_conf(conf);
1305 michael 671
1306 michael 672 assert(aconf->clients > 0);
1307 michael 671
1308 michael 1377 if ((aclass_conf = aconf->class_ptr) != NULL)
1309 adx 30 {
1310 michael 618 aclass = map_to_conf(aclass_conf);
1311 adx 30
1312 michael 672 assert(aclass->curr_user_count > 0);
1313    
1314 adx 30 if (conf->type == CLIENT_TYPE)
1315     remove_from_cidr_check(&client_p->localClient->ip, aclass);
1316 michael 672 if (--aclass->curr_user_count == 0 && aclass->active == 0)
1317 adx 30 delete_conf_item(aclass_conf);
1318     }
1319    
1320 michael 672 if (--aconf->clients == 0 && IsConfIllegal(aconf))
1321     delete_conf_item(conf);
1322    
1323 adx 30 break;
1324 michael 618
1325 adx 30 case LEAF_TYPE:
1326     case HUB_TYPE:
1327 michael 618 match_item = map_to_conf(conf);
1328 adx 30 if (match_item->ref_count == 0 && match_item->illegal)
1329     delete_conf_item(conf);
1330     break;
1331     default:
1332     break;
1333     }
1334    
1335     if (type != CONF_TYPE)
1336     return 0;
1337     }
1338     }
1339    
1340     return -1;
1341     }
1342    
1343     /* attach_conf()
1344     *
1345     * inputs - client pointer
1346     * - conf pointer
1347     * output -
1348     * side effects - Associate a specific configuration entry to a *local*
1349     * client (this is the one which used in accepting the
1350     * connection). Note, that this automatically changes the
1351     * attachment if there was an old one...
1352     */
1353     int
1354     attach_conf(struct Client *client_p, struct ConfItem *conf)
1355     {
1356     if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
1357     return 1;
1358    
1359     if (conf->type == CLIENT_TYPE ||
1360     conf->type == SERVER_TYPE ||
1361     conf->type == OPER_TYPE)
1362     {
1363 michael 618 struct AccessItem *aconf = map_to_conf(conf);
1364 michael 619 struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1365 adx 30
1366     if (IsConfIllegal(aconf))
1367     return NOT_AUTHORIZED;
1368    
1369     if (conf->type == CLIENT_TYPE)
1370     if (cidr_limit_reached(IsConfExemptLimits(aconf),
1371     &client_p->localClient->ip, aclass))
1372 michael 619 return TOO_MANY; /* Already at maximum allowed */
1373 adx 30
1374 michael 1377 aclass->curr_user_count++;
1375 adx 30 aconf->clients++;
1376     }
1377     else if (conf->type == HUB_TYPE || conf->type == LEAF_TYPE)
1378     {
1379 michael 618 struct MatchItem *match_item = map_to_conf(conf);
1380 adx 30 match_item->ref_count++;
1381     }
1382    
1383     dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
1384    
1385     return 0;
1386     }
1387    
1388     /* attach_connect_block()
1389     *
1390     * inputs - pointer to server to attach
1391     * - name of server
1392     * - hostname of server
1393     * output - true (1) if both are found, otherwise return false (0)
1394     * side effects - find connect block and attach them to connecting client
1395     */
1396     int
1397     attach_connect_block(struct Client *client_p, const char *name,
1398     const char *host)
1399     {
1400     dlink_node *ptr;
1401     struct ConfItem *conf;
1402     struct AccessItem *aconf;
1403    
1404     assert(client_p != NULL);
1405     assert(host != NULL);
1406    
1407     if (client_p == NULL || host == NULL)
1408     return 0;
1409    
1410     DLINK_FOREACH(ptr, server_items.head)
1411     {
1412     conf = ptr->data;
1413 michael 618 aconf = map_to_conf(conf);
1414 adx 30
1415     if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
1416     continue;
1417    
1418     attach_conf(client_p, conf);
1419     return -1;
1420     }
1421    
1422     return 0;
1423     }
1424    
1425     /* find_conf_exact()
1426     *
1427     * inputs - type of ConfItem
1428     * - pointer to name to find
1429     * - pointer to username to find
1430     * - pointer to host to find
1431     * output - NULL or pointer to conf found
1432     * side effects - find a conf entry which matches the hostname
1433     * and has the same name.
1434     */
1435     struct ConfItem *
1436     find_conf_exact(ConfType type, const char *name, const char *user,
1437     const char *host)
1438     {
1439     dlink_node *ptr;
1440     dlink_list *list_p;
1441     struct ConfItem *conf = NULL;
1442     struct AccessItem *aconf;
1443    
1444     /* Only valid for OPER_TYPE and ...? */
1445     list_p = map_to_list(type);
1446    
1447     DLINK_FOREACH(ptr, (*list_p).head)
1448     {
1449     conf = ptr->data;
1450    
1451     if (conf->name == NULL)
1452     continue;
1453 michael 815 aconf = map_to_conf(conf);
1454 adx 30 if (aconf->host == NULL)
1455     continue;
1456     if (irccmp(conf->name, name) != 0)
1457     continue;
1458    
1459     /*
1460     ** Accept if the *real* hostname (usually sockethost)
1461     ** socket host) matches *either* host or name field
1462     ** of the configuration.
1463     */
1464 michael 815 if (!match(aconf->host, host) || !match(aconf->user, user))
1465 adx 30 continue;
1466     if (type == OPER_TYPE)
1467     {
1468 michael 815 struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1469 adx 30
1470 michael 1377 if (aconf->clients >= aclass->max_total)
1471 adx 30 continue;
1472     }
1473 michael 815
1474     return conf;
1475 adx 30 }
1476 michael 815
1477 adx 30 return NULL;
1478     }
1479    
1480     /* find_conf_name()
1481     *
1482     * inputs - pointer to conf link list to search
1483     * - pointer to name to find
1484     * - int mask of type of conf to find
1485     * output - NULL or pointer to conf found
1486     * side effects - find a conf entry which matches the name
1487     * and has the given mask.
1488     */
1489     struct ConfItem *
1490     find_conf_name(dlink_list *list, const char *name, ConfType type)
1491     {
1492     dlink_node *ptr;
1493     struct ConfItem* conf;
1494    
1495     DLINK_FOREACH(ptr, list->head)
1496     {
1497     conf = ptr->data;
1498    
1499     if (conf->type == type)
1500     {
1501     if (conf->name && (irccmp(conf->name, name) == 0 ||
1502     match(conf->name, name)))
1503     return conf;
1504     }
1505     }
1506    
1507     return NULL;
1508     }
1509    
1510     /* map_to_list()
1511     *
1512     * inputs - ConfType conf
1513     * output - pointer to dlink_list to use
1514     * side effects - none
1515     */
1516     static dlink_list *
1517     map_to_list(ConfType type)
1518     {
1519     switch(type)
1520     {
1521     case RXLINE_TYPE:
1522     return(&rxconf_items);
1523     break;
1524     case XLINE_TYPE:
1525     return(&xconf_items);
1526     break;
1527     case ULINE_TYPE:
1528     return(&uconf_items);
1529     break;
1530     case NRESV_TYPE:
1531     return(&nresv_items);
1532     break;
1533     case OPER_TYPE:
1534     return(&oconf_items);
1535     break;
1536     case CLASS_TYPE:
1537     return(&class_items);
1538     break;
1539     case SERVER_TYPE:
1540     return(&server_items);
1541     break;
1542 michael 1172 case SERVICE_TYPE:
1543     return(&service_items);
1544     break;
1545 adx 30 case CLUSTER_TYPE:
1546     return(&cluster_items);
1547     break;
1548     case CONF_TYPE:
1549     case GLINE_TYPE:
1550     case KLINE_TYPE:
1551     case DLINE_TYPE:
1552     case CRESV_TYPE:
1553     default:
1554     return NULL;
1555     }
1556     }
1557    
1558     /* find_matching_name_conf()
1559     *
1560     * inputs - type of link list to look in
1561     * - pointer to name string to find
1562     * - pointer to user
1563     * - pointer to host
1564     * - optional action to match on as well
1565     * output - NULL or pointer to found struct MatchItem
1566     * side effects - looks for a match on name field
1567     */
1568     struct ConfItem *
1569     find_matching_name_conf(ConfType type, const char *name, const char *user,
1570     const char *host, int action)
1571     {
1572     dlink_node *ptr=NULL;
1573     struct ConfItem *conf=NULL;
1574     struct AccessItem *aconf=NULL;
1575     struct MatchItem *match_item=NULL;
1576     dlink_list *list_p = map_to_list(type);
1577    
1578     switch (type)
1579     {
1580 michael 1009 #ifdef HAVE_LIBPCRE
1581     case RXLINE_TYPE:
1582 adx 30 DLINK_FOREACH(ptr, list_p->head)
1583     {
1584     conf = ptr->data;
1585     assert(conf->regexpname);
1586    
1587     if (!ircd_pcre_exec(conf->regexpname, name))
1588     return conf;
1589     }
1590     break;
1591 michael 1009 #endif
1592 michael 1157 case SERVICE_TYPE:
1593     DLINK_FOREACH(ptr, list_p->head)
1594     {
1595     conf = ptr->data;
1596    
1597     if (EmptyString(conf->name))
1598     continue;
1599     if ((name != NULL) && !irccmp(name, conf->name))
1600     return conf;
1601     }
1602     break;
1603    
1604 adx 30 case XLINE_TYPE:
1605     case ULINE_TYPE:
1606     case NRESV_TYPE:
1607     DLINK_FOREACH(ptr, list_p->head)
1608     {
1609     conf = ptr->data;
1610    
1611     match_item = map_to_conf(conf);
1612     if (EmptyString(conf->name))
1613     continue;
1614     if ((name != NULL) && match_esc(conf->name, name))
1615     {
1616     if ((user == NULL && (host == NULL)))
1617     return conf;
1618     if ((match_item->action & action) != action)
1619     continue;
1620     if (EmptyString(match_item->user) || EmptyString(match_item->host))
1621     return conf;
1622     if (match(match_item->user, user) && match(match_item->host, host))
1623     return conf;
1624     }
1625     }
1626     break;
1627    
1628     case SERVER_TYPE:
1629     DLINK_FOREACH(ptr, list_p->head)
1630     {
1631     conf = ptr->data;
1632     aconf = map_to_conf(conf);
1633    
1634     if ((name != NULL) && match_esc(name, conf->name))
1635     return conf;
1636     else if ((host != NULL) && match_esc(host, aconf->host))
1637     return conf;
1638     }
1639     break;
1640    
1641     default:
1642     break;
1643     }
1644     return NULL;
1645     }
1646    
1647     /* find_exact_name_conf()
1648     *
1649     * inputs - type of link list to look in
1650     * - pointer to name string to find
1651     * - pointer to user
1652     * - pointer to host
1653     * output - NULL or pointer to found struct MatchItem
1654     * side effects - looks for an exact match on name field
1655     */
1656     struct ConfItem *
1657 michael 1285 find_exact_name_conf(ConfType type, const struct Client *who, const char *name,
1658 adx 30 const char *user, const char *host)
1659     {
1660     dlink_node *ptr = NULL;
1661     struct AccessItem *aconf;
1662     struct ConfItem *conf;
1663     struct MatchItem *match_item;
1664     dlink_list *list_p;
1665    
1666     list_p = map_to_list(type);
1667    
1668     switch(type)
1669     {
1670     case RXLINE_TYPE:
1671     case XLINE_TYPE:
1672     case ULINE_TYPE:
1673     case NRESV_TYPE:
1674    
1675     DLINK_FOREACH(ptr, list_p->head)
1676     {
1677     conf = ptr->data;
1678     match_item = (struct MatchItem *)map_to_conf(conf);
1679     if (EmptyString(conf->name))
1680     continue;
1681    
1682     if (irccmp(conf->name, name) == 0)
1683     {
1684     if ((user == NULL && (host == NULL)))
1685     return (conf);
1686     if (EmptyString(match_item->user) || EmptyString(match_item->host))
1687     return (conf);
1688     if (match(match_item->user, user) && match(match_item->host, host))
1689     return (conf);
1690     }
1691     }
1692     break;
1693    
1694     case OPER_TYPE:
1695     DLINK_FOREACH(ptr, list_p->head)
1696     {
1697     conf = ptr->data;
1698 michael 1285 aconf = map_to_conf(conf);
1699    
1700 adx 30 if (EmptyString(conf->name))
1701 michael 1285 continue;
1702    
1703     if (!irccmp(conf->name, name))
1704 adx 30 {
1705 michael 1285 if (!who)
1706     return conf;
1707     if (EmptyString(aconf->user) || EmptyString(aconf->host))
1708     return conf;
1709     if (match(aconf->user, who->username))
1710     {
1711     switch (aconf->type)
1712     {
1713     case HM_HOST:
1714     if (match(aconf->host, who->host) || match(aconf->host, who->sockhost))
1715     return conf;
1716     break;
1717     case HM_IPV4:
1718     if (who->localClient->aftype == AF_INET)
1719     if (match_ipv4(&who->localClient->ip, &aconf->ipnum, aconf->bits))
1720     return conf;
1721     break;
1722     #ifdef IPV6
1723     case HM_IPV6:
1724     if (who->localClient->aftype == AF_INET6)
1725     if (match_ipv6(&who->localClient->ip, &aconf->ipnum, aconf->bits))
1726     return conf;
1727     break;
1728     #endif
1729     default:
1730     assert(0);
1731     }
1732     }
1733 adx 30 }
1734     }
1735 michael 1285
1736 adx 30 break;
1737    
1738     case SERVER_TYPE:
1739     DLINK_FOREACH(ptr, list_p->head)
1740     {
1741     conf = ptr->data;
1742     aconf = (struct AccessItem *)map_to_conf(conf);
1743     if (EmptyString(conf->name))
1744     continue;
1745    
1746     if (name == NULL)
1747     {
1748     if (EmptyString(aconf->host))
1749     continue;
1750     if (irccmp(aconf->host, host) == 0)
1751     return(conf);
1752     }
1753     else if (irccmp(conf->name, name) == 0)
1754     {
1755     return (conf);
1756     }
1757     }
1758     break;
1759    
1760     case CLASS_TYPE:
1761     DLINK_FOREACH(ptr, list_p->head)
1762     {
1763     conf = ptr->data;
1764     if (EmptyString(conf->name))
1765     continue;
1766    
1767     if (irccmp(conf->name, name) == 0)
1768     return (conf);
1769     }
1770     break;
1771    
1772     default:
1773     break;
1774     }
1775     return(NULL);
1776     }
1777    
1778     /* rehash()
1779     *
1780     * Actual REHASH service routine. Called with sig == 0 if it has been called
1781     * as a result of an operator issuing this command, else assume it has been
1782     * called as a result of the server receiving a HUP signal.
1783     */
1784     int
1785     rehash(int sig)
1786     {
1787     if (sig != 0)
1788     sendto_realops_flags(UMODE_ALL, L_ALL,
1789     "Got signal SIGHUP, reloading ircd.conf file");
1790    
1791     restart_resolver();
1792 michael 1001
1793 adx 30 /* don't close listeners until we know we can go ahead with the rehash */
1794    
1795     /* Check to see if we magically got(or lost) IPv6 support */
1796     check_can_use_v6();
1797    
1798     read_conf_files(0);
1799    
1800     if (ServerInfo.description != NULL)
1801     strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1802    
1803     load_conf_modules();
1804    
1805     flush_deleted_I_P();
1806    
1807     rehashed_klines = 1;
1808 michael 1247 /* XXX */
1809 adx 30 if (ConfigLoggingEntry.use_logging)
1810 michael 1247 log_close_all();
1811 adx 30
1812     return(0);
1813     }
1814    
1815     /* set_default_conf()
1816     *
1817     * inputs - NONE
1818     * output - NONE
1819     * side effects - Set default values here.
1820     * This is called **PRIOR** to parsing the
1821     * configuration file. If you want to do some validation
1822     * of values later, put them in validate_conf().
1823     */
1824     static void
1825     set_default_conf(void)
1826     {
1827     /* verify init_class() ran, this should be an unnecessary check
1828     * but its not much work.
1829     */
1830     assert(class_default == (struct ConfItem *) class_items.tail->data);
1831    
1832     #ifdef HAVE_LIBCRYPTO
1833     ServerInfo.rsa_private_key = NULL;
1834     ServerInfo.rsa_private_key_file = NULL;
1835     #endif
1836    
1837     /* ServerInfo.name is not rehashable */
1838     /* ServerInfo.name = ServerInfo.name; */
1839     ServerInfo.description = NULL;
1840     DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1841     DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1842    
1843     memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1844     ServerInfo.specific_ipv4_vhost = 0;
1845     memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
1846     ServerInfo.specific_ipv6_vhost = 0;
1847    
1848     ServerInfo.max_clients = MAXCLIENTS_MAX;
1849 michael 956
1850     ServerInfo.hub = 0;
1851 adx 30 ServerInfo.dns_host.sin_addr.s_addr = 0;
1852     ServerInfo.dns_host.sin_port = 0;
1853     AdminInfo.name = NULL;
1854     AdminInfo.email = NULL;
1855     AdminInfo.description = NULL;
1856    
1857 michael 1247 log_close_all();
1858    
1859 adx 30 ConfigLoggingEntry.use_logging = 1;
1860    
1861 michael 1243 ConfigChannel.disable_fake_channels = 0;
1862     ConfigChannel.restrict_channels = 0;
1863     ConfigChannel.disable_local_channels = 0;
1864     ConfigChannel.use_invex = 1;
1865     ConfigChannel.use_except = 1;
1866     ConfigChannel.use_knock = 1;
1867 adx 30 ConfigChannel.knock_delay = 300;
1868     ConfigChannel.knock_delay_channel = 60;
1869     ConfigChannel.max_chans_per_user = 15;
1870 michael 1243 ConfigChannel.quiet_on_ban = 1;
1871 adx 30 ConfigChannel.max_bans = 25;
1872     ConfigChannel.default_split_user_count = 0;
1873     ConfigChannel.default_split_server_count = 0;
1874 michael 1243 ConfigChannel.no_join_on_split = 0;
1875     ConfigChannel.no_create_on_split = 0;
1876     ConfigChannel.burst_topicwho = 1;
1877 adx 30
1878 michael 1243 ConfigServerHide.flatten_links = 0;
1879 adx 30 ConfigServerHide.links_delay = 300;
1880 michael 1243 ConfigServerHide.hidden = 0;
1881     ConfigServerHide.disable_hidden = 0;
1882     ConfigServerHide.hide_servers = 0;
1883 adx 30 DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1884 michael 1243 ConfigServerHide.hide_server_ips = 0;
1885 adx 30
1886 michael 876
1887 michael 1157 DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1888 michael 876 ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1889 adx 30 ConfigFileEntry.gline_min_cidr = 16;
1890     ConfigFileEntry.gline_min_cidr6 = 48;
1891 michael 1243 ConfigFileEntry.invisible_on_connect = 1;
1892     ConfigFileEntry.burst_away = 0;
1893     ConfigFileEntry.use_whois_actually = 1;
1894     ConfigFileEntry.tkline_expire_notices = 1;
1895     ConfigFileEntry.hide_spoof_ips = 1;
1896     ConfigFileEntry.ignore_bogus_ts = 0;
1897     ConfigFileEntry.disable_auth = 0;
1898     ConfigFileEntry.disable_remote = 0;
1899 adx 30 ConfigFileEntry.kill_chase_time_limit = 90;
1900 michael 1119 ConfigFileEntry.default_floodcount = 8;
1901 michael 1243 ConfigFileEntry.failed_oper_notice = 1;
1902 michael 1119 ConfigFileEntry.dots_in_ident = 0;
1903 adx 30 ConfigFileEntry.min_nonwildcard = 4;
1904     ConfigFileEntry.min_nonwildcard_simple = 3;
1905     ConfigFileEntry.max_accept = 20;
1906 michael 1243 ConfigFileEntry.anti_nick_flood = 0;
1907 adx 30 ConfigFileEntry.max_nick_time = 20;
1908     ConfigFileEntry.max_nick_changes = 5;
1909 michael 1119 ConfigFileEntry.anti_spam_exit_message_time = 0;
1910 adx 30 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1911 michael 1119 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1912 michael 1243 ConfigFileEntry.kline_with_reason = 1;
1913 adx 30 ConfigFileEntry.kline_reason = NULL;
1914 michael 1243 ConfigFileEntry.warn_no_nline = 1;
1915     ConfigFileEntry.stats_o_oper_only = 0;
1916 adx 30 ConfigFileEntry.stats_k_oper_only = 1; /* masked */
1917     ConfigFileEntry.stats_i_oper_only = 1; /* masked */
1918 michael 1243 ConfigFileEntry.stats_P_oper_only = 0;
1919 adx 30 ConfigFileEntry.caller_id_wait = 60;
1920 michael 1243 ConfigFileEntry.opers_bypass_callerid = 0;
1921 adx 30 ConfigFileEntry.pace_wait = 10;
1922     ConfigFileEntry.pace_wait_simple = 1;
1923 michael 1243 ConfigFileEntry.short_motd = 0;
1924     ConfigFileEntry.ping_cookie = 0;
1925     ConfigFileEntry.no_oper_flood = 0;
1926     ConfigFileEntry.true_no_oper_flood = 0;
1927     ConfigFileEntry.oper_pass_resv = 1;
1928     ConfigFileEntry.glines = 0;
1929 michael 1119 ConfigFileEntry.gline_time = 12 * 3600;
1930 adx 30 ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1931     ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1932 michael 1119 ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1933 adx 264 ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1934 michael 1119 UMODE_OPERWALL | UMODE_WALLOP;
1935 michael 1243 ConfigFileEntry.use_egd = 0;
1936 adx 30 ConfigFileEntry.egdpool_path = NULL;
1937     ConfigFileEntry.throttle_time = 10;
1938     }
1939    
1940     static void
1941     validate_conf(void)
1942     {
1943     if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1944     ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1945    
1946     if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1947     ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1948    
1949     if (ServerInfo.network_name == NULL)
1950     DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1951    
1952     if (ServerInfo.network_desc == NULL)
1953     DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1954    
1955 michael 1157 if (ConfigFileEntry.service_name == NULL)
1956     DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1957    
1958 adx 30 if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1959     (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1960     ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1961 michael 876
1962     ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1963 adx 30 }
1964    
1965 michael 1363 /* read_conf()
1966     *
1967     * inputs - file descriptor pointing to config file to use
1968     * output - None
1969     * side effects - Read configuration file.
1970     */
1971     static void
1972     read_conf(FILE *file)
1973     {
1974     lineno = 0;
1975    
1976     set_default_conf(); /* Set default values prior to conf parsing */
1977     conf_parser_ctx.pass = 1;
1978     yyparse(); /* pick up the classes first */
1979    
1980     rewind(file);
1981    
1982     conf_parser_ctx.pass = 2;
1983     yyparse(); /* Load the values from the conf */
1984     validate_conf(); /* Check to make sure some values are still okay. */
1985     /* Some global values are also loaded here. */
1986     check_class(); /* Make sure classes are valid */
1987     }
1988    
1989 adx 30 /* lookup_confhost()
1990     *
1991     * start DNS lookups of all hostnames in the conf
1992     * line and convert an IP addresses in a.b.c.d number for to IP#s.
1993     */
1994     static void
1995     lookup_confhost(struct ConfItem *conf)
1996     {
1997     struct AccessItem *aconf;
1998     struct addrinfo hints, *res;
1999    
2000     aconf = map_to_conf(conf);
2001    
2002     if (EmptyString(aconf->host) ||
2003     EmptyString(aconf->user))
2004     {
2005 michael 1247 ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
2006 adx 30 aconf->host, conf->name);
2007     return;
2008     }
2009    
2010     if (strchr(aconf->host, '*') ||
2011     strchr(aconf->host, '?'))
2012     return;
2013    
2014     /* Do name lookup now on hostnames given and store the
2015     * ip numbers in conf structure.
2016     */
2017     memset(&hints, 0, sizeof(hints));
2018    
2019     hints.ai_family = AF_UNSPEC;
2020     hints.ai_socktype = SOCK_STREAM;
2021    
2022     /* Get us ready for a bind() and don't bother doing dns lookup */
2023     hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
2024    
2025 michael 1123 if (getaddrinfo(aconf->host, NULL, &hints, &res))
2026 adx 30 {
2027     conf_dns_lookup(aconf);
2028     return;
2029     }
2030    
2031     assert(res != NULL);
2032    
2033     memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
2034     aconf->ipnum.ss_len = res->ai_addrlen;
2035     aconf->ipnum.ss.ss_family = res->ai_family;
2036 michael 1123 freeaddrinfo(res);
2037 adx 30 }
2038    
2039     /* conf_connect_allowed()
2040     *
2041     * inputs - pointer to inaddr
2042     * - int type ipv4 or ipv6
2043     * output - BANNED or accepted
2044     * side effects - none
2045     */
2046     int
2047     conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
2048     {
2049     struct ip_entry *ip_found;
2050     struct AccessItem *aconf = find_dline_conf(addr, aftype);
2051    
2052     /* DLINE exempt also gets you out of static limits/pacing... */
2053     if (aconf && (aconf->status & CONF_EXEMPTDLINE))
2054     return 0;
2055    
2056     if (aconf != NULL)
2057     return BANNED_CLIENT;
2058    
2059     ip_found = find_or_add_ip(addr);
2060    
2061     if ((CurrentTime - ip_found->last_attempt) <
2062     ConfigFileEntry.throttle_time)
2063     {
2064     ip_found->last_attempt = CurrentTime;
2065     return TOO_FAST;
2066     }
2067    
2068     ip_found->last_attempt = CurrentTime;
2069     return 0;
2070     }
2071    
2072     static struct AccessItem *
2073     find_regexp_kline(const char *uhi[])
2074     {
2075 michael 1009 #ifdef HAVE_LIBPCRE
2076 adx 30 const dlink_node *ptr = NULL;
2077    
2078     DLINK_FOREACH(ptr, rkconf_items.head)
2079     {
2080     struct AccessItem *aptr = map_to_conf(ptr->data);
2081    
2082     assert(aptr->regexuser);
2083     assert(aptr->regexhost);
2084    
2085     if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2086     (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2087     !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2088     return aptr;
2089     }
2090 michael 1009 #endif
2091 adx 30 return NULL;
2092     }
2093    
2094     /* find_kill()
2095     *
2096     * inputs - pointer to client structure
2097     * output - pointer to struct AccessItem if found
2098     * side effects - See if this user is klined already,
2099     * and if so, return struct AccessItem pointer
2100     */
2101     struct AccessItem *
2102     find_kill(struct Client *client_p)
2103     {
2104     struct AccessItem *aconf = NULL;
2105     const char *uhi[3];
2106    
2107     uhi[0] = client_p->username;
2108     uhi[1] = client_p->host;
2109     uhi[2] = client_p->sockhost;
2110    
2111     assert(client_p != NULL);
2112    
2113     aconf = find_kline_conf(client_p->host, client_p->username,
2114     &client_p->localClient->ip,
2115     client_p->localClient->aftype);
2116     if (aconf == NULL)
2117     aconf = find_regexp_kline(uhi);
2118    
2119     if (aconf && (aconf->status & CONF_KLINE))
2120     return aconf;
2121    
2122     return NULL;
2123     }
2124    
2125     struct AccessItem *
2126     find_gline(struct Client *client_p)
2127     {
2128     struct AccessItem *aconf;
2129    
2130     assert(client_p != NULL);
2131    
2132     aconf = find_gline_conf(client_p->host, client_p->username,
2133     &client_p->localClient->ip,
2134     client_p->localClient->aftype);
2135    
2136     if (aconf && (aconf->status & CONF_GLINE))
2137     return aconf;
2138    
2139     return NULL;
2140     }
2141    
2142     /* add_temp_line()
2143     *
2144     * inputs - pointer to struct ConfItem
2145     * output - none
2146     * Side effects - links in given struct ConfItem into
2147     * temporary *line link list
2148     */
2149     void
2150     add_temp_line(struct ConfItem *conf)
2151     {
2152 michael 1369 if (conf->type == XLINE_TYPE)
2153 adx 30 {
2154     conf->flags |= CONF_FLAGS_TEMPORARY;
2155     dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2156     }
2157     else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2158     {
2159     conf->flags |= CONF_FLAGS_TEMPORARY;
2160     dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2161     }
2162     }
2163    
2164     /* cleanup_tklines()
2165     *
2166     * inputs - NONE
2167     * output - NONE
2168     * side effects - call function to expire temporary k/d lines
2169     * This is an event started off in ircd.c
2170     */
2171     void
2172     cleanup_tklines(void *notused)
2173     {
2174 michael 1369 hostmask_expire_temporary();
2175 adx 30 expire_tklines(&temporary_xlines);
2176     expire_tklines(&temporary_resv);
2177     }
2178    
2179     /* expire_tklines()
2180     *
2181     * inputs - tkline list pointer
2182     * output - NONE
2183     * side effects - expire tklines
2184     */
2185     static void
2186     expire_tklines(dlink_list *tklist)
2187     {
2188     dlink_node *ptr;
2189     dlink_node *next_ptr;
2190     struct ConfItem *conf;
2191     struct MatchItem *xconf;
2192     struct MatchItem *nconf;
2193     struct ResvChannel *cconf;
2194    
2195     DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
2196     {
2197     conf = ptr->data;
2198    
2199 michael 1369 if (conf->type == XLINE_TYPE)
2200 adx 30 {
2201     xconf = (struct MatchItem *)map_to_conf(conf);
2202     if (xconf->hold <= CurrentTime)
2203     {
2204     if (ConfigFileEntry.tkline_expire_notices)
2205     sendto_realops_flags(UMODE_ALL, L_ALL,
2206 michael 1369 "Temporary X-line for [%s] sexpired", conf->name);
2207 adx 30 dlinkDelete(ptr, tklist);
2208     free_dlink_node(ptr);
2209     delete_conf_item(conf);
2210     }
2211     }
2212     else if (conf->type == NRESV_TYPE)
2213     {
2214     nconf = (struct MatchItem *)map_to_conf(conf);
2215     if (nconf->hold <= CurrentTime)
2216     {
2217     if (ConfigFileEntry.tkline_expire_notices)
2218     sendto_realops_flags(UMODE_ALL, L_ALL,
2219     "Temporary RESV for [%s] expired", conf->name);
2220     dlinkDelete(ptr, tklist);
2221     free_dlink_node(ptr);
2222     delete_conf_item(conf);
2223     }
2224     }
2225     else if (conf->type == CRESV_TYPE)
2226     {
2227     cconf = (struct ResvChannel *)map_to_conf(conf);
2228     if (cconf->hold <= CurrentTime)
2229     {
2230     if (ConfigFileEntry.tkline_expire_notices)
2231     sendto_realops_flags(UMODE_ALL, L_ALL,
2232     "Temporary RESV for [%s] expired", cconf->name);
2233 db 855 delete_channel_resv(cconf);
2234 adx 30 }
2235     }
2236     }
2237     }
2238    
2239     /* oper_privs_as_string()
2240     *
2241 michael 58 * inputs - pointer to client_p
2242 adx 30 * output - pointer to static string showing oper privs
2243     * side effects - return as string, the oper privs as derived from port
2244     */
2245 michael 58 static const struct oper_privs
2246     {
2247     const unsigned int oprivs;
2248     const unsigned char c;
2249     } flag_list[] = {
2250 michael 1294 { OPER_FLAG_ADMIN, 'A' },
2251     { OPER_FLAG_REMOTEBAN, 'B' },
2252     { OPER_FLAG_DIE, 'D' },
2253     { OPER_FLAG_GLINE, 'G' },
2254     { OPER_FLAG_REHASH, 'H' },
2255     { OPER_FLAG_K, 'K' },
2256     { OPER_FLAG_OPERWALL, 'L' },
2257     { OPER_FLAG_N, 'N' },
2258     { OPER_FLAG_GLOBAL_KILL, 'O' },
2259     { OPER_FLAG_REMOTE, 'R' },
2260     { OPER_FLAG_OPER_SPY, 'S' },
2261     { OPER_FLAG_UNKLINE, 'U' },
2262     { OPER_FLAG_X, 'X' },
2263     { 0, '\0' }
2264 michael 58 };
2265 adx 30
2266     char *
2267     oper_privs_as_string(const unsigned int port)
2268     {
2269 michael 58 static char privs_out[16];
2270     char *privs_ptr = privs_out;
2271     unsigned int i = 0;
2272 adx 30
2273 michael 58 for (; flag_list[i].oprivs; ++i)
2274     {
2275 michael 1294 if (port & flag_list[i].oprivs)
2276 michael 58 *privs_ptr++ = flag_list[i].c;
2277     else
2278     *privs_ptr++ = ToLowerTab[flag_list[i].c];
2279     }
2280    
2281     *privs_ptr = '\0';
2282    
2283 adx 30 return privs_out;
2284     }
2285    
2286     /*
2287     * Input: A client to find the active oper{} name for.
2288     * Output: The nick!user@host{oper} of the oper.
2289     * "oper" is server name for remote opers
2290     * Side effects: None.
2291     */
2292 michael 1364 const char *
2293 adx 30 get_oper_name(const struct Client *client_p)
2294     {
2295 michael 1364 dlink_node *cnode = NULL;
2296 adx 30 /* +5 for !,@,{,} and null */
2297 michael 1147 static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
2298 adx 30
2299     if (MyConnect(client_p))
2300     {
2301 michael 1364 if ((cnode = client_p->localClient->confs.head))
2302 adx 30 {
2303 michael 1364 struct ConfItem *conf = cnode->data;
2304     const struct AccessItem *aconf = map_to_conf(conf);
2305 adx 30
2306     if (IsConfOperator(aconf))
2307     {
2308 michael 1147 snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
2309     client_p->username, client_p->host, conf->name);
2310 adx 30 return buffer;
2311     }
2312     }
2313    
2314     /* Probably should assert here for now. If there is an oper out there
2315     * with no oper{} conf attached, it would be good for us to know...
2316     */
2317     assert(0); /* Oper without oper conf! */
2318     }
2319    
2320 michael 1147 snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
2321     client_p->username, client_p->host, client_p->servptr->name);
2322 adx 30 return buffer;
2323     }
2324    
2325     /* read_conf_files()
2326     *
2327     * inputs - cold start YES or NO
2328     * output - none
2329     * side effects - read all conf files needed, ircd.conf kline.conf etc.
2330     */
2331     void
2332     read_conf_files(int cold)
2333     {
2334     const char *filename;
2335     char chanmodes[32];
2336     char chanlimit[32];
2337    
2338 michael 967 conf_parser_ctx.boot = cold;
2339 adx 30 filename = get_conf_name(CONF_TYPE);
2340    
2341     /* We need to know the initial filename for the yyerror() to report
2342     FIXME: The full path is in conffilenamebuf first time since we
2343     dont know anything else
2344    
2345     - Gozem 2002-07-21
2346     */
2347     strlcpy(conffilebuf, filename, sizeof(conffilebuf));
2348    
2349 michael 1325 if ((conf_parser_ctx.conf_file = fopen(filename, "r")) == NULL)
2350 adx 30 {
2351     if (cold)
2352     {
2353 michael 1247 ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2354 adx 30 filename, strerror(errno));
2355     exit(-1);
2356     }
2357     else
2358     {
2359     sendto_realops_flags(UMODE_ALL, L_ALL,
2360     "Unable to read configuration file '%s': %s",
2361     filename, strerror(errno));
2362     return;
2363     }
2364     }
2365    
2366     if (!cold)
2367     clear_out_old_conf();
2368    
2369 michael 967 read_conf(conf_parser_ctx.conf_file);
2370 michael 1325 fclose(conf_parser_ctx.conf_file);
2371 adx 30
2372     add_isupport("NETWORK", ServerInfo.network_name, -1);
2373 michael 1147 snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
2374     ConfigChannel.use_except ? "e" : "",
2375     ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
2376 adx 30 add_isupport("MAXLIST", chanmodes, -1);
2377     add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
2378 michael 1147
2379 adx 30 if (ConfigChannel.disable_local_channels)
2380     add_isupport("CHANTYPES", "#", -1);
2381     else
2382     add_isupport("CHANTYPES", "#&", -1);
2383 michael 1147
2384     snprintf(chanlimit, sizeof(chanlimit), "%s:%d",
2385     ConfigChannel.disable_local_channels ? "#" : "#&",
2386     ConfigChannel.max_chans_per_user);
2387 adx 30 add_isupport("CHANLIMIT", chanlimit, -1);
2388 michael 1147 snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
2389     ConfigChannel.use_except ? "e" : "",
2390 michael 1175 ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
2391 michael 100 add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2392 michael 1147
2393 adx 30 if (ConfigChannel.use_except)
2394     add_isupport("EXCEPTS", "e", -1);
2395     if (ConfigChannel.use_invex)
2396     add_isupport("INVEX", "I", -1);
2397     add_isupport("CHANMODES", chanmodes, -1);
2398    
2399     /*
2400     * message_locale may have changed. rebuild isupport since it relies
2401     * on strlen(form_str(RPL_ISUPPORT))
2402     */
2403     rebuild_isupport_message_line();
2404    
2405 michael 1009 #ifdef HAVE_LIBPCRE
2406     parse_conf_file(RKLINE_TYPE, cold);
2407     parse_conf_file(RXLINE_TYPE, cold);
2408     #endif
2409 adx 30 parse_conf_file(KLINE_TYPE, cold);
2410     parse_conf_file(DLINE_TYPE, cold);
2411     parse_conf_file(XLINE_TYPE, cold);
2412     parse_conf_file(NRESV_TYPE, cold);
2413     parse_conf_file(CRESV_TYPE, cold);
2414     }
2415    
2416     /* parse_conf_file()
2417     *
2418     * inputs - type of conf file to parse
2419     * output - none
2420     * side effects - conf file for givenconf type is opened and read then parsed
2421     */
2422     static void
2423     parse_conf_file(int type, int cold)
2424     {
2425 michael 1325 FILE *file = NULL;
2426 adx 30 const char *filename = get_conf_name(type);
2427    
2428 michael 1325 if ((file = fopen(filename, "r")) == NULL)
2429 adx 30 {
2430     if (cold)
2431 michael 1247 ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2432 adx 30 filename, strerror(errno));
2433     else
2434     sendto_realops_flags(UMODE_ALL, L_ALL,
2435     "Unable to read configuration file '%s': %s",
2436     filename, strerror(errno));
2437     }
2438     else
2439     {
2440     parse_csv_file(file, type);
2441 michael 1325 fclose(file);
2442 adx 30 }
2443     }
2444    
2445     /* clear_out_old_conf()
2446     *
2447     * inputs - none
2448     * output - none
2449     * side effects - Clear out the old configuration
2450     */
2451     static void
2452     clear_out_old_conf(void)
2453     {
2454     dlink_node *ptr = NULL, *next_ptr = NULL;
2455     struct ConfItem *conf;
2456     struct AccessItem *aconf;
2457     struct ClassItem *cltmp;
2458     struct MatchItem *match_item;
2459     dlink_list *free_items [] = {
2460     &server_items, &oconf_items, &hub_items, &leaf_items,
2461     &uconf_items, &xconf_items, &rxconf_items, &rkconf_items,
2462 michael 1157 &nresv_items, &cluster_items, &gdeny_items, &service_items, NULL
2463 adx 30 };
2464    
2465     dlink_list ** iterator = free_items; /* C is dumb */
2466    
2467     /* We only need to free anything allocated by yyparse() here.
2468     * Resetting structs, etc, is taken care of by set_default_conf().
2469     */
2470    
2471     for (; *iterator != NULL; iterator++)
2472     {
2473     DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2474     {
2475     conf = ptr->data;
2476     /* XXX This is less than pretty */
2477     if (conf->type == SERVER_TYPE)
2478     {
2479 michael 671 aconf = map_to_conf(conf);
2480    
2481 adx 30 if (aconf->clients != 0)
2482     {
2483     SetConfIllegal(aconf);
2484     dlinkDelete(&conf->node, &server_items);
2485     }
2486     else
2487     {
2488     delete_conf_item(conf);
2489     }
2490     }
2491     else if (conf->type == OPER_TYPE)
2492     {
2493 michael 671 aconf = map_to_conf(conf);
2494    
2495 adx 30 if (aconf->clients != 0)
2496     {
2497