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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (hide annotations)
Sun Oct 2 20:50:00 2005 UTC (17 years, 8 months ago) by knight
Original Path: ircd-hybrid/src/s_conf.c
File MIME type: text/x-chdr
File size: 100366 byte(s)
- svn:keywords

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