ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 575
Committed: Mon May 1 11:41:09 2006 UTC (17 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 101575 byte(s)
Log Message:
- Fixed a bunch of compile warnings

File Contents

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

Properties

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