ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/s_conf.c
Revision: 62
Committed: Mon Oct 3 22:23:39 2005 UTC (19 years, 10 months ago) by adx
Content type: text/x-csrc
File size: 101308 byte(s)
Log Message:
- reorganisation goes on, removed external references from libio/mem

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

Properties

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