ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 891
Committed: Thu Nov 1 13:44:50 2007 UTC (16 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 100603 byte(s)
Log Message:
- Avoid useless irc_getnameinfo calls in several places

File Contents

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

Properties

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