ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/s_conf.c
Revision: 1005
Committed: Mon Aug 31 23:07:43 2009 UTC (14 years, 6 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 99440 byte(s)
Log Message:
- remove conf_add_d_conf wrapper

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

Properties

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