/[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 896 - (hide annotations)
Sat Nov 3 08:54:09 2007 UTC (15 years, 7 months ago) by michael
Original Path: ircd-hybrid-7.2/src/s_conf.c
File MIME type: text/x-chdr
File size: 100577 byte(s)
- Killed s_stats.c

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