ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/s_conf.c
Revision: 956
Committed: Mon Jul 27 00:34:48 2009 UTC (14 years, 8 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 100546 byte(s)
Log Message:
- removed LL leftover in set_default_conf(). now ServerInfo.hub
  properly initializes on /rehash

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * s_conf.c: Configuration file functions.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26     #include "ircd_defs.h"
27     #include "tools.h"
28     #include "s_conf.h"
29     #include "s_serv.h"
30     #include "resv.h"
31     #include "channel.h"
32     #include "client.h"
33     #include "common.h"
34     #include "event.h"
35     #include "hash.h"
36     #include "hook.h"
37     #include "irc_string.h"
38     #include "sprintf_irc.h"
39     #include "s_bsd.h"
40     #include "irc_getaddrinfo.h"
41     #include "ircd.h"
42     #include "list.h"
43     #include "listener.h"
44     #include "hostmask.h"
45     #include "modules.h"
46     #include "numeric.h"
47     #include "fdlist.h"
48     #include "s_log.h"
49     #include "send.h"
50     #include "s_gline.h"
51     #include "fileio.h"
52     #include "memory.h"
53     #include "irc_res.h"
54     #include "userhost.h"
55     #include "s_user.h"
56     #include "channel_mode.h"
57    
58     struct Callback *client_check_cb = NULL;
59     struct config_server_hide ConfigServerHide;
60    
61     /* general conf items link list root, other than k lines etc. */
62     dlink_list server_items = { NULL, NULL, 0 };
63     dlink_list cluster_items = { NULL, NULL, 0 };
64     dlink_list hub_items = { NULL, NULL, 0 };
65     dlink_list leaf_items = { NULL, NULL, 0 };
66     dlink_list oconf_items = { NULL, NULL, 0 };
67     dlink_list uconf_items = { NULL, NULL, 0 };
68     dlink_list xconf_items = { NULL, NULL, 0 };
69     dlink_list rxconf_items = { NULL, NULL, 0 };
70     dlink_list rkconf_items = { NULL, NULL, 0 };
71     dlink_list nresv_items = { NULL, NULL, 0 };
72     dlink_list class_items = { NULL, NULL, 0 };
73     dlink_list gdeny_items = { NULL, NULL, 0 };
74    
75     dlink_list temporary_klines = { NULL, NULL, 0 };
76     dlink_list temporary_dlines = { NULL, NULL, 0 };
77     dlink_list temporary_xlines = { NULL, NULL, 0 };
78     dlink_list temporary_rklines = { NULL, NULL, 0 };
79     dlink_list temporary_glines = { NULL, NULL, 0 };
80     dlink_list temporary_rxlines = { NULL, NULL, 0 };
81     dlink_list temporary_resv = { NULL, NULL, 0 };
82    
83     extern unsigned int lineno;
84     extern char linebuf[];
85     extern char conffilebuf[IRCD_BUFSIZE];
86     extern char yytext[];
87     extern int yyparse(); /* defined in y.tab.c */
88 michael 593 int ypass = 1; /* used by yyparse() */
89 adx 30
90     /* internally defined functions */
91     static void lookup_confhost(struct ConfItem *);
92     static void set_default_conf(void);
93     static void validate_conf(void);
94     static void read_conf(FBFILE *);
95     static void clear_out_old_conf(void);
96     static void flush_deleted_I_P(void);
97     static void expire_tklines(dlink_list *);
98     static void garbage_collect_ip_entries(void);
99     static int hash_ip(struct irc_ssaddr *);
100     static int verify_access(struct Client *, const char *);
101     static int attach_iline(struct Client *, struct ConfItem *);
102     static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
103     static void parse_conf_file(int, int);
104     static dlink_list *map_to_list(ConfType);
105     static struct AccessItem *find_regexp_kline(const char *[]);
106     static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
107    
108     /*
109     * bit_len
110     */
111     static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
112     static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
113     static void destroy_cidr_class(struct ClassItem *);
114    
115     static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
116    
117     FBFILE *conf_fbfile_in = NULL;
118    
119     /* address of default class conf */
120     static struct ConfItem *class_default;
121    
122     /* usually, with hash tables, you use a prime number...
123     * but in this case I am dealing with ip addresses,
124     * not ascii strings.
125     */
126     #define IP_HASH_SIZE 0x1000
127    
128     struct ip_entry
129     {
130     struct irc_ssaddr ip;
131     int count;
132     time_t last_attempt;
133     struct ip_entry *next;
134     };
135    
136     static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
137     static BlockHeap *ip_entry_heap = NULL;
138     static int ip_entries_count = 0;
139    
140    
141     inline void *
142     map_to_conf(struct ConfItem *aconf)
143     {
144     void *conf;
145     conf = (void *)((unsigned long)aconf +
146     (unsigned long)sizeof(struct ConfItem));
147     return(conf);
148     }
149    
150     inline struct ConfItem *
151     unmap_conf_item(void *aconf)
152     {
153     struct ConfItem *conf;
154    
155     conf = (struct ConfItem *)((unsigned long)aconf -
156     (unsigned long)sizeof(struct ConfItem));
157     return(conf);
158     }
159    
160     /* conf_dns_callback()
161     *
162     * inputs - pointer to struct AccessItem
163     * - pointer to DNSReply reply
164     * output - none
165     * side effects - called when resolver query finishes
166     * if the query resulted in a successful search, hp will contain
167     * a non-null pointer, otherwise hp will be null.
168     * if successful save hp in the conf item it was called with
169     */
170     static void
171     conf_dns_callback(void *vptr, struct DNSReply *reply)
172     {
173     struct AccessItem *aconf = (struct AccessItem *)vptr;
174     struct ConfItem *conf;
175    
176     MyFree(aconf->dns_query);
177     aconf->dns_query = NULL;
178    
179     if (reply != NULL)
180     memcpy(&aconf->ipnum, &reply->addr, sizeof(reply->addr));
181     else {
182     ilog(L_NOTICE, "Host not found: %s, ignoring connect{} block",
183     aconf->host);
184     conf = unmap_conf_item(aconf);
185     sendto_realops_flags(UMODE_ALL, L_ALL,
186     "Ignoring connect{} block for %s - host not found",
187     conf->name);
188     delete_conf_item(conf);
189     }
190     }
191    
192     /* conf_dns_lookup()
193     *
194     * do a nameserver lookup of the conf host
195     * if the conf entry is currently doing a ns lookup do nothing, otherwise
196     * allocate a dns_query and start ns lookup.
197     */
198     static void
199     conf_dns_lookup(struct AccessItem *aconf)
200     {
201     if (aconf->dns_query == NULL)
202     {
203     aconf->dns_query = MyMalloc(sizeof(struct DNSQuery));
204     aconf->dns_query->ptr = aconf;
205     aconf->dns_query->callback = conf_dns_callback;
206     gethost_byname(aconf->host, aconf->dns_query);
207     }
208     }
209    
210     /* make_conf_item()
211     *
212     * inputs - type of item
213     * output - pointer to new conf entry
214     * side effects - none
215     */
216     struct ConfItem *
217     make_conf_item(ConfType type)
218     {
219     struct ConfItem *conf = NULL;
220     struct AccessItem *aconf = NULL;
221     struct ClassItem *aclass = NULL;
222     int status = 0;
223    
224     switch (type)
225     {
226     case DLINE_TYPE:
227     case EXEMPTDLINE_TYPE:
228     case GLINE_TYPE:
229     case KLINE_TYPE:
230     case CLIENT_TYPE:
231     case OPER_TYPE:
232     case SERVER_TYPE:
233     conf = MyMalloc(sizeof(struct ConfItem) +
234     sizeof(struct AccessItem));
235     aconf = map_to_conf(conf);
236     aconf->aftype = AF_INET;
237    
238     /* Yes, sigh. switch on type again */
239     switch (type)
240     {
241     case EXEMPTDLINE_TYPE:
242     status = CONF_EXEMPTDLINE;
243     break;
244    
245     case DLINE_TYPE:
246     status = CONF_DLINE;
247     break;
248    
249     case KLINE_TYPE:
250     status = CONF_KLINE;
251     break;
252    
253     case GLINE_TYPE:
254     status = CONF_GLINE;
255     break;
256    
257     case CLIENT_TYPE:
258     status = CONF_CLIENT;
259     break;
260    
261     case OPER_TYPE:
262     status = CONF_OPERATOR;
263     dlinkAdd(conf, &conf->node, &oconf_items);
264     break;
265    
266     case SERVER_TYPE:
267     status = CONF_SERVER;
268     dlinkAdd(conf, &conf->node, &server_items);
269     break;
270    
271     default:
272     break;
273     }
274     aconf->status = status;
275     break;
276    
277     case LEAF_TYPE:
278     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
279     sizeof(struct MatchItem));
280     dlinkAdd(conf, &conf->node, &leaf_items);
281     break;
282    
283     case HUB_TYPE:
284     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
285     sizeof(struct MatchItem));
286     dlinkAdd(conf, &conf->node, &hub_items);
287     break;
288    
289     case ULINE_TYPE:
290     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
291     sizeof(struct MatchItem));
292     dlinkAdd(conf, &conf->node, &uconf_items);
293     break;
294    
295     case GDENY_TYPE:
296     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
297     sizeof(struct AccessItem));
298 michael 102 dlinkAdd(conf, &conf->node, &gdeny_items);
299 adx 30 break;
300    
301     case XLINE_TYPE:
302     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
303     sizeof(struct MatchItem));
304     dlinkAdd(conf, &conf->node, &xconf_items);
305     break;
306    
307     case RXLINE_TYPE:
308     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
309     sizeof(struct MatchItem));
310     dlinkAdd(conf, &conf->node, &rxconf_items);
311     break;
312    
313     case RKLINE_TYPE:
314     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
315     sizeof(struct AccessItem));
316     aconf = map_to_conf(conf);
317     aconf->status = CONF_KLINE;
318     dlinkAdd(conf, &conf->node, &rkconf_items);
319     break;
320    
321     case CLUSTER_TYPE:
322     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
323     dlinkAdd(conf, &conf->node, &cluster_items);
324     break;
325    
326     case CRESV_TYPE:
327     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
328     sizeof(struct ResvChannel));
329     break;
330    
331     case NRESV_TYPE:
332     conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
333     sizeof(struct MatchItem));
334     dlinkAdd(conf, &conf->node, &nresv_items);
335     break;
336    
337     case CLASS_TYPE:
338 michael 671 conf = MyMalloc(sizeof(struct ConfItem) +
339     sizeof(struct ClassItem));
340 adx 30 dlinkAdd(conf, &conf->node, &class_items);
341 michael 671
342     aclass = map_to_conf(conf);
343     aclass->active = 1;
344     ConFreq(aclass) = DEFAULT_CONNECTFREQUENCY;
345 adx 30 PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
346     MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
347     MaxSendq(aclass) = DEFAULT_SENDQ;
348 michael 671
349 adx 30 break;
350    
351     default:
352     conf = NULL;
353     break;
354     }
355    
356     /* XXX Yes, this will core if default is hit. I want it to for now - db */
357     conf->type = type;
358    
359 michael 671 return conf;
360 adx 30 }
361    
362     void
363     delete_conf_item(struct ConfItem *conf)
364     {
365 michael 433 dlink_node *m = NULL;
366 adx 30 struct MatchItem *match_item;
367     struct AccessItem *aconf;
368     ConfType type = conf->type;
369    
370     MyFree(conf->name);
371     conf->name = NULL;
372    
373     switch(type)
374     {
375     case DLINE_TYPE:
376     case EXEMPTDLINE_TYPE:
377     case GLINE_TYPE:
378     case KLINE_TYPE:
379     case CLIENT_TYPE:
380     case OPER_TYPE:
381     case SERVER_TYPE:
382     aconf = map_to_conf(conf);
383    
384     if (aconf->dns_query != NULL)
385     {
386     delete_resolver_queries(aconf->dns_query);
387     MyFree(aconf->dns_query);
388     }
389     if (aconf->passwd != NULL)
390     memset(aconf->passwd, 0, strlen(aconf->passwd));
391     if (aconf->spasswd != NULL)
392     memset(aconf->spasswd, 0, strlen(aconf->spasswd));
393     aconf->class_ptr = NULL;
394    
395     MyFree(aconf->passwd);
396     MyFree(aconf->spasswd);
397     MyFree(aconf->reason);
398     MyFree(aconf->oper_reason);
399     MyFree(aconf->user);
400     MyFree(aconf->host);
401     MyFree(aconf->fakename);
402     #ifdef HAVE_LIBCRYPTO
403     if (aconf->rsa_public_key)
404     RSA_free(aconf->rsa_public_key);
405     MyFree(aconf->rsa_public_key_file);
406     #endif
407    
408     /* Yes, sigh. switch on type again */
409     switch(type)
410     {
411     case EXEMPTDLINE_TYPE:
412     case DLINE_TYPE:
413     case GLINE_TYPE:
414     case KLINE_TYPE:
415     case CLIENT_TYPE:
416     MyFree(conf);
417     break;
418    
419     case OPER_TYPE:
420     aconf = map_to_conf(conf);
421     if (!IsConfIllegal(aconf))
422     dlinkDelete(&conf->node, &oconf_items);
423     MyFree(conf);
424     break;
425    
426     case SERVER_TYPE:
427     aconf = map_to_conf(conf);
428     if (!IsConfIllegal(aconf))
429     dlinkDelete(&conf->node, &server_items);
430     MyFree(conf);
431     break;
432    
433     default:
434     break;
435     }
436     break;
437    
438     case HUB_TYPE:
439     match_item = map_to_conf(conf);
440     MyFree(match_item->user);
441     MyFree(match_item->host);
442     MyFree(match_item->reason);
443     MyFree(match_item->oper_reason);
444     /* If marked illegal, its already been pulled off of the hub_items list */
445     if (!match_item->illegal)
446     dlinkDelete(&conf->node, &hub_items);
447     MyFree(conf);
448     break;
449    
450     case LEAF_TYPE:
451     match_item = map_to_conf(conf);
452     MyFree(match_item->user);
453     MyFree(match_item->host);
454     MyFree(match_item->reason);
455     MyFree(match_item->oper_reason);
456     /* If marked illegal, its already been pulled off of the leaf_items list */
457     if (!match_item->illegal)
458     dlinkDelete(&conf->node, &leaf_items);
459     MyFree(conf);
460     break;
461    
462     case ULINE_TYPE:
463     match_item = map_to_conf(conf);
464     MyFree(match_item->user);
465     MyFree(match_item->host);
466     MyFree(match_item->reason);
467     MyFree(match_item->oper_reason);
468     dlinkDelete(&conf->node, &uconf_items);
469     MyFree(conf);
470     break;
471    
472     case XLINE_TYPE:
473     match_item = map_to_conf(conf);
474     MyFree(match_item->user);
475     MyFree(match_item->host);
476     MyFree(match_item->reason);
477     MyFree(match_item->oper_reason);
478     dlinkDelete(&conf->node, &xconf_items);
479     MyFree(conf);
480     break;
481    
482     case RKLINE_TYPE:
483     aconf = map_to_conf(conf);
484     MyFree(aconf->regexuser);
485     MyFree(aconf->regexhost);
486     MyFree(aconf->user);
487     MyFree(aconf->host);
488     MyFree(aconf->reason);
489     MyFree(aconf->oper_reason);
490     dlinkDelete(&conf->node, &rkconf_items);
491     MyFree(conf);
492     break;
493    
494     case RXLINE_TYPE:
495     MyFree(conf->regexpname);
496     match_item = map_to_conf(conf);
497     MyFree(match_item->user);
498     MyFree(match_item->host);
499     MyFree(match_item->reason);
500     MyFree(match_item->oper_reason);
501     dlinkDelete(&conf->node, &rxconf_items);
502     MyFree(conf);
503     break;
504    
505     case NRESV_TYPE:
506     match_item = map_to_conf(conf);
507     MyFree(match_item->user);
508     MyFree(match_item->host);
509     MyFree(match_item->reason);
510     MyFree(match_item->oper_reason);
511     dlinkDelete(&conf->node, &nresv_items);
512 michael 433
513     if (conf->flags & CONF_FLAGS_TEMPORARY)
514     if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
515     free_dlink_node(m);
516    
517 adx 30 MyFree(conf);
518     break;
519    
520     case GDENY_TYPE:
521     aconf = map_to_conf(conf);
522     MyFree(aconf->user);
523     MyFree(aconf->host);
524     dlinkDelete(&conf->node, &gdeny_items);
525     MyFree(conf);
526     break;
527    
528     case CLUSTER_TYPE:
529     dlinkDelete(&conf->node, &cluster_items);
530     MyFree(conf);
531     break;
532    
533     case CRESV_TYPE:
534 michael 433 if (conf->flags & CONF_FLAGS_TEMPORARY)
535     if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
536     free_dlink_node(m);
537    
538 adx 30 MyFree(conf);
539     break;
540    
541     case CLASS_TYPE:
542     dlinkDelete(&conf->node, &class_items);
543     MyFree(conf);
544     break;
545    
546     default:
547     break;
548     }
549     }
550    
551     /* free_access_item()
552     *
553     * inputs - pointer to conf to free
554     * output - none
555     * side effects - crucial password fields are zeroed, conf is freed
556     */
557     void
558     free_access_item(struct AccessItem *aconf)
559     {
560     struct ConfItem *conf;
561    
562     if (aconf == NULL)
563     return;
564     conf = unmap_conf_item(aconf);
565     delete_conf_item(conf);
566     }
567    
568     static const unsigned int shared_bit_table[] =
569     { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
570    
571     /* report_confitem_types()
572     *
573     * inputs - pointer to client requesting confitem report
574     * - ConfType to report
575     * output - none
576     * side effects -
577     */
578     void
579     report_confitem_types(struct Client *source_p, ConfType type, int temp)
580     {
581     dlink_node *ptr = NULL;
582     struct ConfItem *conf = NULL;
583     struct AccessItem *aconf = NULL;
584     struct MatchItem *matchitem = NULL;
585     struct ClassItem *classitem = NULL;
586     char buf[12];
587     char *p = NULL;
588 michael 575 const char *pfx = NULL;
589 adx 30
590     switch (type)
591     {
592     case GDENY_TYPE:
593     DLINK_FOREACH(ptr, gdeny_items.head)
594     {
595     conf = ptr->data;
596     aconf = map_to_conf(conf);
597    
598     p = buf;
599    
600     if (aconf->flags & GDENY_BLOCK)
601     *p++ = 'B';
602     else
603     *p++ = 'b';
604    
605     if (aconf->flags & GDENY_REJECT)
606     *p++ = 'R';
607     else
608     *p++ = 'r';
609    
610     *p = '\0';
611    
612     sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
613     me.name, RPL_STATSDEBUG, source_p->name,
614     aconf->user, aconf->host, conf->name, buf);
615     }
616     break;
617    
618     case XLINE_TYPE:
619     DLINK_FOREACH(ptr, xconf_items.head)
620     {
621     conf = ptr->data;
622     matchitem = map_to_conf(conf);
623    
624     sendto_one(source_p, form_str(RPL_STATSXLINE),
625     me.name, source_p->name,
626     matchitem->hold ? "x": "X", matchitem->count,
627     conf->name, matchitem->reason);
628     }
629     break;
630    
631     case RXLINE_TYPE:
632     DLINK_FOREACH(ptr, rxconf_items.head)
633     {
634     conf = ptr->data;
635     matchitem = map_to_conf(conf);
636    
637     sendto_one(source_p, form_str(RPL_STATSXLINE),
638     me.name, source_p->name,
639     matchitem->hold ? "xR": "XR", matchitem->count,
640     conf->name, matchitem->reason);
641     }
642     break;
643    
644     case RKLINE_TYPE:
645 michael 596 pfx = temp ? "kR" : "KR";
646 adx 30
647     DLINK_FOREACH(ptr, rkconf_items.head)
648     {
649     aconf = map_to_conf((conf = ptr->data));
650    
651     if (temp && !(conf->flags & CONF_FLAGS_TEMPORARY))
652     continue;
653    
654     sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
655 michael 575 source_p->name, pfx, aconf->host, aconf->user,
656 adx 30 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
657     }
658     break;
659    
660     case ULINE_TYPE:
661     DLINK_FOREACH(ptr, uconf_items.head)
662     {
663     conf = ptr->data;
664     matchitem = map_to_conf(conf);
665    
666     p = buf;
667    
668     /* some of these are redundant for the sake of
669     * consistency with cluster{} flags
670     */
671     *p++ = 'c';
672     flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
673    
674     sendto_one(source_p, form_str(RPL_STATSULINE),
675     me.name, source_p->name, conf->name,
676     matchitem->user?matchitem->user: "*",
677     matchitem->host?matchitem->host: "*", buf);
678     }
679    
680     DLINK_FOREACH(ptr, cluster_items.head)
681     {
682     conf = ptr->data;
683    
684     p = buf;
685    
686     *p++ = 'C';
687     flags_to_ascii(conf->flags, shared_bit_table, p, 0);
688    
689     sendto_one(source_p, form_str(RPL_STATSULINE),
690     me.name, source_p->name, conf->name,
691     "*", "*", buf);
692     }
693    
694     break;
695    
696     case OPER_TYPE:
697     DLINK_FOREACH(ptr, oconf_items.head)
698     {
699     conf = ptr->data;
700     aconf = map_to_conf(conf);
701    
702     /* Don't allow non opers to see oper privs */
703     if (IsOper(source_p))
704     sendto_one(source_p, form_str(RPL_STATSOLINE),
705     me.name, source_p->name, 'O', aconf->user, aconf->host,
706     conf->name, oper_privs_as_string(aconf->port),
707     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
708     else
709     sendto_one(source_p, form_str(RPL_STATSOLINE),
710     me.name, source_p->name, 'O', aconf->user, aconf->host,
711     conf->name, "0",
712     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
713     }
714     break;
715    
716     case CLASS_TYPE:
717     DLINK_FOREACH(ptr, class_items.head)
718     {
719     conf = ptr->data;
720     classitem = map_to_conf(conf);
721     sendto_one(source_p, form_str(RPL_STATSYLINE),
722     me.name, source_p->name, 'Y',
723     conf->name, PingFreq(classitem),
724     ConFreq(classitem),
725 michael 619 MaxTotal(classitem), MaxSendq(classitem),
726 michael 671 CurrUserCount(classitem),
727     classitem->active ? "active" : "disabled");
728 adx 30 }
729     break;
730    
731     case CONF_TYPE:
732     case CLIENT_TYPE:
733     break;
734    
735     case SERVER_TYPE:
736     DLINK_FOREACH(ptr, server_items.head)
737     {
738     p = buf;
739    
740     conf = ptr->data;
741     aconf = map_to_conf(conf);
742    
743     buf[0] = '\0';
744    
745     if (IsConfAllowAutoConn(aconf))
746     *p++ = 'A';
747     if (IsConfCryptLink(aconf))
748     *p++ = 'C';
749     if (aconf->fakename)
750     *p++ = 'M';
751     if (IsConfTopicBurst(aconf))
752     *p++ = 'T';
753     if (IsConfCompressed(aconf))
754     *p++ = 'Z';
755     if (buf[0] == '\0')
756     *p++ = '*';
757    
758     *p = '\0';
759    
760 michael 671 /*
761     * Allow admins to see actual ips unless hide_server_ips is enabled
762 adx 30 */
763     if (!ConfigServerHide.hide_server_ips && IsAdmin(source_p))
764     sendto_one(source_p, form_str(RPL_STATSCLINE),
765     me.name, source_p->name, 'C', aconf->host,
766     buf, conf->name, aconf->port,
767     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
768     else
769     sendto_one(source_p, form_str(RPL_STATSCLINE),
770     me.name, source_p->name, 'C',
771     "*@127.0.0.1", buf, conf->name, aconf->port,
772     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
773     }
774     break;
775    
776     case HUB_TYPE:
777     DLINK_FOREACH(ptr, hub_items.head)
778     {
779     conf = ptr->data;
780     matchitem = map_to_conf(conf);
781     sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
782     source_p->name, 'H', matchitem->host, conf->name, 0, "*");
783     }
784     break;
785    
786     case LEAF_TYPE:
787     DLINK_FOREACH(ptr, leaf_items.head)
788     {
789     conf = ptr->data;
790     matchitem = map_to_conf(conf);
791     sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
792     source_p->name, 'L', matchitem->host, conf->name, 0, "*");
793     }
794     break;
795    
796     case GLINE_TYPE:
797     case KLINE_TYPE:
798     case DLINE_TYPE:
799     case EXEMPTDLINE_TYPE:
800     case CRESV_TYPE:
801     case NRESV_TYPE:
802     case CLUSTER_TYPE:
803     break;
804     }
805     }
806    
807     /* check_client()
808     *
809     * inputs - pointer to client
810     * output - 0 = Success
811     * NOT_AUTHORIZED (-1) = Access denied (no I line match)
812     * IRCD_SOCKET_ERROR (-2) = Bad socket.
813     * I_LINE_FULL (-3) = I-line is full
814     * TOO_MANY (-4) = Too many connections from hostname
815     * BANNED_CLIENT (-5) = K-lined
816     * side effects - Ordinary client access check.
817     * Look for conf lines which have the same
818     * status as the flags passed.
819     */
820     static void *
821     check_client(va_list args)
822     {
823     struct Client *source_p = va_arg(args, struct Client *);
824     const char *username = va_arg(args, const char *);
825     int i;
826    
827     /* I'm already in big trouble if source_p->localClient is NULL -db */
828     if ((i = verify_access(source_p, username)))
829     ilog(L_INFO, "Access denied: %s[%s]",
830     source_p->name, source_p->sockhost);
831    
832     switch (i)
833     {
834     case TOO_MANY:
835     sendto_realops_flags(UMODE_FULL, L_ALL,
836     "Too many on IP for %s (%s).",
837     get_client_name(source_p, SHOW_IP),
838     source_p->sockhost);
839     ilog(L_INFO,"Too many connections on IP from %s.",
840     get_client_name(source_p, SHOW_IP));
841 michael 896 ++ServerStats.is_ref;
842 adx 30 exit_client(source_p, &me, "No more connections allowed on that IP");
843     break;
844    
845     case I_LINE_FULL:
846     sendto_realops_flags(UMODE_FULL, L_ALL,
847     "I-line is full for %s (%s).",
848     get_client_name(source_p, SHOW_IP),
849     source_p->sockhost);
850     ilog(L_INFO,"Too many connections from %s.",
851     get_client_name(source_p, SHOW_IP));
852 michael 896 ++ServerStats.is_ref;
853 adx 30 exit_client(source_p, &me,
854     "No more connections allowed in your connection class");
855     break;
856    
857     case NOT_AUTHORIZED:
858 michael 896 ++ServerStats.is_ref;
859 adx 30 /* jdc - lists server name & port connections are on */
860     /* a purely cosmetical change */
861     sendto_realops_flags(UMODE_UNAUTH, L_ALL,
862     "Unauthorized client connection from %s [%s] on [%s/%u].",
863     get_client_name(source_p, SHOW_IP),
864 michael 891 source_p->sockhost,
865 adx 30 source_p->localClient->listener->name,
866     source_p->localClient->listener->port);
867     ilog(L_INFO,
868     "Unauthorized client connection from %s on [%s/%u].",
869     get_client_name(source_p, SHOW_IP),
870     source_p->localClient->listener->name,
871     source_p->localClient->listener->port);
872    
873     /* XXX It is prolematical whether it is better to use the
874     * capture reject code here or rely on the connecting too fast code.
875     * - Dianora
876     */
877 michael 671 if (REJECT_HOLD_TIME > 0)
878 adx 30 {
879     sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
880     me.name, source_p->name);
881     source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
882     SetCaptured(source_p);
883     }
884     else
885     exit_client(source_p, &me, "You are not authorized to use this server");
886     break;
887 michael 891
888 adx 30 case BANNED_CLIENT:
889     /*
890     * Don't exit them immediately, play with them a bit.
891     * - Dianora
892     */
893     if (REJECT_HOLD_TIME > 0)
894     {
895     source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
896     SetCaptured(source_p);
897     }
898     else
899     exit_client(source_p, &me, "Banned");
900 michael 896 ++ServerStats.is_ref;
901 adx 30 break;
902    
903     case 0:
904     default:
905     break;
906     }
907    
908     return (i < 0 ? NULL : source_p);
909     }
910    
911     /* verify_access()
912     *
913     * inputs - pointer to client to verify
914     * - pointer to proposed username
915     * output - 0 if success -'ve if not
916     * side effect - find the first (best) I line to attach.
917     */
918     static int
919     verify_access(struct Client *client_p, const char *username)
920     {
921     struct AccessItem *aconf = NULL, *rkconf = NULL;
922     struct ConfItem *conf = NULL;
923     char non_ident[USERLEN + 1] = { '~', '\0' };
924     const char *uhi[3];
925    
926     if (IsGotId(client_p))
927     {
928     aconf = find_address_conf(client_p->host, client_p->username,
929     &client_p->localClient->ip,
930     client_p->localClient->aftype,
931     client_p->localClient->passwd);
932     }
933     else
934     {
935     strlcpy(non_ident+1, username, sizeof(non_ident)-1);
936     aconf = find_address_conf(client_p->host,non_ident,
937     &client_p->localClient->ip,
938     client_p->localClient->aftype,
939     client_p->localClient->passwd);
940     }
941    
942     uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
943     uhi[1] = client_p->host;
944     uhi[2] = client_p->sockhost;
945    
946     rkconf = find_regexp_kline(uhi);
947    
948     if (aconf != NULL)
949     {
950     if (IsConfClient(aconf) && !rkconf)
951     {
952     conf = unmap_conf_item(aconf);
953    
954     if (IsConfRedir(aconf))
955     {
956     sendto_one(client_p, form_str(RPL_REDIR),
957     me.name, client_p->name,
958     conf->name ? conf->name : "",
959     aconf->port);
960     return(NOT_AUTHORIZED);
961     }
962    
963     if (IsConfDoIdentd(aconf))
964     SetNeedId(client_p);
965    
966     /* Thanks for spoof idea amm */
967     if (IsConfDoSpoofIp(aconf))
968     {
969     conf = unmap_conf_item(aconf);
970    
971     if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
972     sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
973     client_p->name, client_p->host, conf->name);
974     strlcpy(client_p->host, conf->name, sizeof(client_p->host));
975     SetIPSpoof(client_p);
976     }
977    
978     return(attach_iline(client_p, conf));
979     }
980     else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
981     {
982     /* XXX */
983     aconf = rkconf ? rkconf : aconf;
984     if (IsConfGline(aconf))
985     sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
986     client_p->name);
987     if (ConfigFileEntry.kline_with_reason)
988     sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
989     me.name, client_p->name, aconf->reason);
990     return(BANNED_CLIENT);
991     }
992     }
993    
994     return(NOT_AUTHORIZED);
995     }
996    
997     /* attach_iline()
998     *
999     * inputs - client pointer
1000     * - conf pointer
1001     * output -
1002     * side effects - do actual attach
1003     */
1004     static int
1005     attach_iline(struct Client *client_p, struct ConfItem *conf)
1006     {
1007     struct AccessItem *aconf;
1008     struct ClassItem *aclass;
1009     struct ip_entry *ip_found;
1010     int a_limit_reached = 0;
1011     int local = 0, global = 0, ident = 0;
1012    
1013     ip_found = find_or_add_ip(&client_p->localClient->ip);
1014     ip_found->count++;
1015     SetIpHash(client_p);
1016    
1017 michael 624 aconf = map_to_conf(conf);
1018 adx 30 if (aconf->class_ptr == NULL)
1019     return NOT_AUTHORIZED; /* If class is missing, this is best */
1020    
1021 michael 624 aclass = map_to_conf(aconf->class_ptr);
1022 adx 30
1023     count_user_host(client_p->username, client_p->host,
1024     &global, &local, &ident);
1025    
1026     /* XXX blah. go down checking the various silly limits
1027     * setting a_limit_reached if any limit is reached.
1028     * - Dianora
1029     */
1030     if (MaxTotal(aclass) != 0 && CurrUserCount(aclass) >= MaxTotal(aclass))
1031     a_limit_reached = 1;
1032 michael 624 else if (MaxPerIp(aclass) != 0 && ip_found->count > MaxPerIp(aclass))
1033 adx 30 a_limit_reached = 1;
1034     else if (MaxLocal(aclass) != 0 && local >= MaxLocal(aclass))
1035     a_limit_reached = 1;
1036     else if (MaxGlobal(aclass) != 0 && global >= MaxGlobal(aclass))
1037     a_limit_reached = 1;
1038     else if (MaxIdent(aclass) != 0 && ident >= MaxIdent(aclass) &&
1039     client_p->username[0] != '~')
1040     a_limit_reached = 1;
1041    
1042     if (a_limit_reached)
1043     {
1044     if (!IsConfExemptLimits(aconf))
1045 michael 624 return TOO_MANY; /* Already at maximum allowed */
1046 adx 30
1047     sendto_one(client_p,
1048     ":%s NOTICE %s :*** Your connection class is full, "
1049     "but you have exceed_limit = yes;", me.name, client_p->name);
1050     }
1051    
1052     return attach_conf(client_p, conf);
1053     }
1054    
1055     /* init_ip_hash_table()
1056     *
1057     * inputs - NONE
1058     * output - NONE
1059     * side effects - allocate memory for ip_entry(s)
1060     * - clear the ip hash table
1061     */
1062     void
1063     init_ip_hash_table(void)
1064     {
1065     ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
1066     2 * hard_fdlimit);
1067     memset(ip_hash_table, 0, sizeof(ip_hash_table));
1068     }
1069    
1070     /* find_or_add_ip()
1071     *
1072     * inputs - pointer to struct irc_ssaddr
1073     * output - pointer to a struct ip_entry
1074     * side effects -
1075     *
1076     * If the ip # was not found, a new struct ip_entry is created, and the ip
1077     * count set to 0.
1078     */
1079     static struct ip_entry *
1080     find_or_add_ip(struct irc_ssaddr *ip_in)
1081     {
1082     struct ip_entry *ptr, *newptr;
1083     int hash_index = hash_ip(ip_in), res;
1084     struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1085     #ifdef IPV6
1086     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1087     #endif
1088    
1089     for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1090     {
1091     #ifdef IPV6
1092     if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1093     continue;
1094     if (ip_in->ss.ss_family == AF_INET6)
1095     {
1096     ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1097     res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1098     }
1099     else
1100     #endif
1101     {
1102     ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1103     res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1104     }
1105     if (res == 0)
1106     {
1107     /* Found entry already in hash, return it. */
1108     return ptr;
1109     }
1110     }
1111    
1112     if (ip_entries_count >= 2 * hard_fdlimit)
1113     garbage_collect_ip_entries();
1114    
1115     newptr = BlockHeapAlloc(ip_entry_heap);
1116     ip_entries_count++;
1117     memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
1118    
1119     newptr->next = ip_hash_table[hash_index];
1120     ip_hash_table[hash_index] = newptr;
1121    
1122     return newptr;
1123     }
1124    
1125     /* remove_one_ip()
1126     *
1127     * inputs - unsigned long IP address value
1128     * output - NONE
1129     * side effects - The ip address given, is looked up in ip hash table
1130     * and number of ip#'s for that ip decremented.
1131     * If ip # count reaches 0 and has expired,
1132     * the struct ip_entry is returned to the ip_entry_heap
1133     */
1134     void
1135     remove_one_ip(struct irc_ssaddr *ip_in)
1136     {
1137     struct ip_entry *ptr;
1138     struct ip_entry *last_ptr = NULL;
1139     int hash_index = hash_ip(ip_in), res;
1140     struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1141     #ifdef IPV6
1142     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1143     #endif
1144    
1145     for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1146     {
1147     #ifdef IPV6
1148     if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1149     continue;
1150     if (ip_in->ss.ss_family == AF_INET6)
1151     {
1152     ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1153     res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1154     }
1155     else
1156     #endif
1157     {
1158     ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1159     res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1160     }
1161     if (res)
1162     continue;
1163     if (ptr->count > 0)
1164     ptr->count--;
1165     if (ptr->count == 0 &&
1166     (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1167     {
1168     if (last_ptr != NULL)
1169     last_ptr->next = ptr->next;
1170     else
1171     ip_hash_table[hash_index] = ptr->next;
1172    
1173     BlockHeapFree(ip_entry_heap, ptr);
1174     ip_entries_count--;
1175     return;
1176     }
1177     last_ptr = ptr;
1178     }
1179     }
1180    
1181     /* hash_ip()
1182     *
1183     * input - pointer to an irc_inaddr
1184     * output - integer value used as index into hash table
1185     * side effects - hopefully, none
1186     */
1187     static int
1188     hash_ip(struct irc_ssaddr *addr)
1189     {
1190     if (addr->ss.ss_family == AF_INET)
1191     {
1192     struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
1193     int hash;
1194     u_int32_t ip;
1195    
1196     ip = ntohl(v4->sin_addr.s_addr);
1197     hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
1198     return hash;
1199     }
1200     #ifdef IPV6
1201     else
1202     {
1203     int hash;
1204     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
1205     u_int32_t *ip = (u_int32_t *)&v6->sin6_addr.s6_addr;
1206    
1207     hash = ip[0] ^ ip[3];
1208     hash ^= hash >> 16;
1209     hash ^= hash >> 8;
1210     hash = hash & (IP_HASH_SIZE - 1);
1211     return hash;
1212     }
1213     #else
1214     return 0;
1215     #endif
1216     }
1217    
1218     /* count_ip_hash()
1219     *
1220     * inputs - pointer to counter of number of ips hashed
1221     * - pointer to memory used for ip hash
1222     * output - returned via pointers input
1223     * side effects - NONE
1224     *
1225     * number of hashed ip #'s is counted up, plus the amount of memory
1226     * used in the hash.
1227     */
1228     void
1229 michael 948 count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
1230 adx 30 {
1231     struct ip_entry *ptr;
1232     int i;
1233    
1234     *number_ips_stored = 0;
1235     *mem_ips_stored = 0;
1236    
1237     for (i = 0; i < IP_HASH_SIZE; i++)
1238     {
1239     for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
1240     {
1241     *number_ips_stored += 1;
1242     *mem_ips_stored += sizeof(struct ip_entry);
1243     }
1244     }
1245     }
1246    
1247     /* garbage_collect_ip_entries()
1248     *
1249     * input - NONE
1250     * output - NONE
1251     * side effects - free up all ip entries with no connections
1252     */
1253     static void
1254     garbage_collect_ip_entries(void)
1255     {
1256     struct ip_entry *ptr;
1257     struct ip_entry *last_ptr;
1258     struct ip_entry *next_ptr;
1259     int i;
1260    
1261     for (i = 0; i < IP_HASH_SIZE; i++)
1262     {
1263     last_ptr = NULL;
1264    
1265     for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
1266     {
1267     next_ptr = ptr->next;
1268    
1269     if (ptr->count == 0 &&
1270     (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1271     {
1272     if (last_ptr != NULL)
1273     last_ptr->next = ptr->next;
1274     else
1275     ip_hash_table[i] = ptr->next;
1276     BlockHeapFree(ip_entry_heap, ptr);
1277     ip_entries_count--;
1278     }
1279     else
1280     last_ptr = ptr;
1281     }
1282     }
1283     }
1284    
1285     /* detach_conf()
1286     *
1287     * inputs - pointer to client to detach
1288     * - type of conf to detach
1289     * output - 0 for success, -1 for failure
1290     * side effects - Disassociate configuration from the client.
1291     * Also removes a class from the list if marked for deleting.
1292     */
1293     int
1294     detach_conf(struct Client *client_p, ConfType type)
1295     {
1296     dlink_node *ptr, *next_ptr;
1297     struct ConfItem *conf;
1298     struct ClassItem *aclass;
1299     struct AccessItem *aconf;
1300     struct ConfItem *aclass_conf;
1301     struct MatchItem *match_item;
1302    
1303     DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
1304     {
1305     conf = ptr->data;
1306    
1307     if (type == CONF_TYPE || conf->type == type)
1308     {
1309     dlinkDelete(ptr, &client_p->localClient->confs);
1310     free_dlink_node(ptr);
1311    
1312     switch (conf->type)
1313     {
1314     case CLIENT_TYPE:
1315     case OPER_TYPE:
1316     case SERVER_TYPE:
1317 michael 618 aconf = map_to_conf(conf);
1318 michael 671
1319 michael 672 assert(aconf->clients > 0);
1320 michael 671
1321 adx 30 if ((aclass_conf = ClassPtr(aconf)) != NULL)
1322     {
1323 michael 618 aclass = map_to_conf(aclass_conf);
1324 adx 30
1325 michael 672 assert(aclass->curr_user_count > 0);
1326    
1327 adx 30 if (conf->type == CLIENT_TYPE)
1328     remove_from_cidr_check(&client_p->localClient->ip, aclass);
1329 michael 672 if (--aclass->curr_user_count == 0 && aclass->active == 0)
1330 adx 30 delete_conf_item(aclass_conf);
1331     }
1332    
1333 michael 672 if (--aconf->clients == 0 && IsConfIllegal(aconf))
1334     delete_conf_item(conf);
1335    
1336 adx 30 break;
1337 michael 618
1338 adx 30 case LEAF_TYPE:
1339     case HUB_TYPE:
1340 michael 618 match_item = map_to_conf(conf);
1341 adx 30 if (match_item->ref_count == 0 && match_item->illegal)
1342     delete_conf_item(conf);
1343     break;
1344     default:
1345     break;
1346     }
1347    
1348     if (type != CONF_TYPE)
1349     return 0;
1350     }
1351     }
1352    
1353     return -1;
1354     }
1355    
1356     /* attach_conf()
1357     *
1358     * inputs - client pointer
1359     * - conf pointer
1360     * output -
1361     * side effects - Associate a specific configuration entry to a *local*
1362     * client (this is the one which used in accepting the
1363     * connection). Note, that this automatically changes the
1364     * attachment if there was an old one...
1365     */
1366     int
1367     attach_conf(struct Client *client_p, struct ConfItem *conf)
1368     {
1369     if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
1370     return 1;
1371    
1372     if (conf->type == CLIENT_TYPE ||
1373     conf->type == SERVER_TYPE ||
1374     conf->type == OPER_TYPE)
1375     {
1376 michael 618 struct AccessItem *aconf = map_to_conf(conf);
1377 michael 619 struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1378 adx 30
1379     if (IsConfIllegal(aconf))
1380     return NOT_AUTHORIZED;
1381    
1382     if (conf->type == CLIENT_TYPE)
1383     if (cidr_limit_reached(IsConfExemptLimits(aconf),
1384     &client_p->localClient->ip, aclass))
1385 michael 619 return TOO_MANY; /* Already at maximum allowed */
1386 adx 30
1387 michael 618 CurrUserCount(aclass)++;
1388 adx 30 aconf->clients++;
1389     }
1390     else if (conf->type == HUB_TYPE || conf->type == LEAF_TYPE)
1391     {
1392 michael 618 struct MatchItem *match_item = map_to_conf(conf);
1393 adx 30 match_item->ref_count++;
1394     }
1395    
1396     dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
1397    
1398     return 0;
1399     }
1400    
1401     /* attach_connect_block()
1402     *
1403     * inputs - pointer to server to attach
1404     * - name of server
1405     * - hostname of server
1406     * output - true (1) if both are found, otherwise return false (0)
1407     * side effects - find connect block and attach them to connecting client
1408     */
1409     int
1410     attach_connect_block(struct Client *client_p, const char *name,
1411     const char *host)
1412     {
1413     dlink_node *ptr;
1414     struct ConfItem *conf;
1415     struct AccessItem *aconf;
1416    
1417     assert(client_p != NULL);
1418     assert(host != NULL);
1419    
1420     if (client_p == NULL || host == NULL)
1421     return 0;
1422    
1423     DLINK_FOREACH(ptr, server_items.head)
1424     {
1425     conf = ptr->data;
1426 michael 618 aconf = map_to_conf(conf);
1427 adx 30
1428     if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
1429     continue;
1430    
1431     attach_conf(client_p, conf);
1432     return -1;
1433     }
1434    
1435     return 0;
1436     }
1437    
1438     /* find_conf_exact()
1439     *
1440     * inputs - type of ConfItem
1441     * - pointer to name to find
1442     * - pointer to username to find
1443     * - pointer to host to find
1444     * output - NULL or pointer to conf found
1445     * side effects - find a conf entry which matches the hostname
1446     * and has the same name.
1447     */
1448     struct ConfItem *
1449     find_conf_exact(ConfType type, const char *name, const char *user,
1450     const char *host)
1451     {
1452     dlink_node *ptr;
1453     dlink_list *list_p;
1454     struct ConfItem *conf = NULL;
1455     struct AccessItem *aconf;
1456    
1457     /* Only valid for OPER_TYPE and ...? */
1458     list_p = map_to_list(type);
1459    
1460     DLINK_FOREACH(ptr, (*list_p).head)
1461     {
1462     conf = ptr->data;
1463    
1464     if (conf->name == NULL)
1465     continue;
1466 michael 815 aconf = map_to_conf(conf);
1467 adx 30 if (aconf->host == NULL)
1468     continue;
1469     if (irccmp(conf->name, name) != 0)
1470     continue;
1471    
1472     /*
1473     ** Accept if the *real* hostname (usually sockethost)
1474     ** socket host) matches *either* host or name field
1475     ** of the configuration.
1476     */
1477 michael 815 if (!match(aconf->host, host) || !match(aconf->user, user))
1478 adx 30 continue;
1479     if (type == OPER_TYPE)
1480     {
1481 michael 815 struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1482 adx 30
1483 michael 815 if (aconf->clients >= MaxTotal(aclass))
1484 adx 30 continue;
1485     }
1486 michael 815
1487     return conf;
1488 adx 30 }
1489 michael 815
1490 adx 30 return NULL;
1491     }
1492    
1493     /* find_conf_name()
1494     *
1495     * inputs - pointer to conf link list to search
1496     * - pointer to name to find
1497     * - int mask of type of conf to find
1498     * output - NULL or pointer to conf found
1499     * side effects - find a conf entry which matches the name
1500     * and has the given mask.
1501     */
1502     struct ConfItem *
1503     find_conf_name(dlink_list *list, const char *name, ConfType type)
1504     {
1505     dlink_node *ptr;
1506     struct ConfItem* conf;
1507    
1508     DLINK_FOREACH(ptr, list->head)
1509     {
1510     conf = ptr->data;
1511    
1512     if (conf->type == type)
1513     {
1514     if (conf->name && (irccmp(conf->name, name) == 0 ||
1515     match(conf->name, name)))
1516     return conf;
1517     }
1518     }
1519    
1520     return NULL;
1521     }
1522    
1523     /* map_to_list()
1524     *
1525     * inputs - ConfType conf
1526     * output - pointer to dlink_list to use
1527     * side effects - none
1528     */
1529     static dlink_list *
1530     map_to_list(ConfType type)
1531     {
1532     switch(type)
1533     {
1534     case RXLINE_TYPE:
1535     return(&rxconf_items);
1536     break;
1537     case XLINE_TYPE:
1538     return(&xconf_items);
1539     break;
1540     case ULINE_TYPE:
1541     return(&uconf_items);
1542     break;
1543     case NRESV_TYPE:
1544     return(&nresv_items);
1545     break;
1546     case OPER_TYPE:
1547     return(&oconf_items);
1548     break;
1549     case CLASS_TYPE:
1550     return(&class_items);
1551     break;
1552     case SERVER_TYPE:
1553     return(&server_items);
1554     break;
1555     case CLUSTER_TYPE:
1556     return(&cluster_items);
1557     break;
1558     case CONF_TYPE:
1559     case GLINE_TYPE:
1560     case KLINE_TYPE:
1561     case DLINE_TYPE:
1562     case CRESV_TYPE:
1563     default:
1564     return NULL;
1565     }
1566     }
1567    
1568     /* find_matching_name_conf()
1569     *
1570     * inputs - type of link list to look in
1571     * - pointer to name string to find
1572     * - pointer to user
1573     * - pointer to host
1574     * - optional action to match on as well
1575     * output - NULL or pointer to found struct MatchItem
1576     * side effects - looks for a match on name field
1577     */
1578     struct ConfItem *
1579     find_matching_name_conf(ConfType type, const char *name, const char *user,
1580     const char *host, int action)
1581     {
1582     dlink_node *ptr=NULL;
1583     struct ConfItem *conf=NULL;
1584     struct AccessItem *aconf=NULL;
1585     struct MatchItem *match_item=NULL;
1586     dlink_list *list_p = map_to_list(type);
1587    
1588     switch (type)
1589     {
1590     case RXLINE_TYPE:
1591     DLINK_FOREACH(ptr, list_p->head)
1592     {
1593     conf = ptr->data;
1594     assert(conf->regexpname);
1595    
1596     if (!ircd_pcre_exec(conf->regexpname, name))
1597     return conf;
1598     }
1599     break;
1600    
1601     case XLINE_TYPE:
1602     case ULINE_TYPE:
1603     case NRESV_TYPE:
1604     DLINK_FOREACH(ptr, list_p->head)
1605     {
1606     conf = ptr->data;
1607    
1608     match_item = map_to_conf(conf);
1609     if (EmptyString(conf->name))
1610     continue;
1611     if ((name != NULL) && match_esc(conf->name, name))
1612     {
1613     if ((user == NULL && (host == NULL)))
1614     return conf;
1615     if ((match_item->action & action) != action)
1616     continue;
1617     if (EmptyString(match_item->user) || EmptyString(match_item->host))
1618     return conf;
1619     if (match(match_item->user, user) && match(match_item->host, host))
1620     return conf;
1621     }
1622     }
1623     break;
1624    
1625     case SERVER_TYPE:
1626     DLINK_FOREACH(ptr, list_p->head)
1627     {
1628     conf = ptr->data;
1629     aconf = map_to_conf(conf);
1630    
1631     if ((name != NULL) && match_esc(name, conf->name))
1632     return conf;
1633     else if ((host != NULL) && match_esc(host, aconf->host))
1634     return conf;
1635     }
1636     break;
1637    
1638     default:
1639     break;
1640     }
1641     return NULL;
1642     }
1643    
1644     /* find_exact_name_conf()
1645     *
1646     * inputs - type of link list to look in
1647     * - pointer to name string to find
1648     * - pointer to user
1649     * - pointer to host
1650     * output - NULL or pointer to found struct MatchItem
1651     * side effects - looks for an exact match on name field
1652     */
1653     struct ConfItem *
1654     find_exact_name_conf(ConfType type, const char *name,
1655     const char *user, const char *host)
1656     {
1657     dlink_node *ptr = NULL;
1658     struct AccessItem *aconf;
1659     struct ConfItem *conf;
1660     struct MatchItem *match_item;
1661     dlink_list *list_p;
1662    
1663     list_p = map_to_list(type);
1664    
1665     switch(type)
1666     {
1667     case RXLINE_TYPE:
1668     case XLINE_TYPE:
1669     case ULINE_TYPE:
1670     case NRESV_TYPE:
1671    
1672     DLINK_FOREACH(ptr, list_p->head)
1673     {
1674     conf = ptr->data;
1675     match_item = (struct MatchItem *)map_to_conf(conf);
1676     if (EmptyString(conf->name))
1677     continue;
1678    
1679     if (irccmp(conf->name, name) == 0)
1680     {
1681     if ((user == NULL && (host == NULL)))
1682     return (conf);
1683     if (EmptyString(match_item->user) || EmptyString(match_item->host))
1684     return (conf);
1685     if (match(match_item->user, user) && match(match_item->host, host))
1686     return (conf);
1687     }
1688     }
1689     break;
1690    
1691     case OPER_TYPE:
1692     DLINK_FOREACH(ptr, list_p->head)
1693     {
1694     conf = ptr->data;
1695     aconf = (struct AccessItem *)map_to_conf(conf);
1696     if (EmptyString(conf->name))
1697     continue;
1698    
1699     if (irccmp(conf->name, name) == 0)
1700     {
1701     if ((user == NULL && (host == NULL)))
1702     return (conf);
1703     if (EmptyString(aconf->user) || EmptyString(aconf->host))
1704     return (conf);
1705     if (match(aconf->user, user) && match(aconf->host, host))
1706     return (conf);
1707     }
1708     }
1709     break;
1710    
1711     case SERVER_TYPE:
1712     DLINK_FOREACH(ptr, list_p->head)
1713     {
1714     conf = ptr->data;
1715     aconf = (struct AccessItem *)map_to_conf(conf);
1716     if (EmptyString(conf->name))
1717     continue;
1718    
1719     if (name == NULL)
1720     {
1721     if (EmptyString(aconf->host))
1722     continue;
1723     if (irccmp(aconf->host, host) == 0)
1724     return(conf);
1725     }
1726     else if (irccmp(conf->name, name) == 0)
1727     {
1728     return (conf);
1729     }
1730     }
1731     break;
1732    
1733     case CLASS_TYPE:
1734     DLINK_FOREACH(ptr, list_p->head)
1735     {
1736     conf = ptr->data;
1737     if (EmptyString(conf->name))
1738     continue;
1739    
1740     if (irccmp(conf->name, name) == 0)
1741     return (conf);
1742     }
1743     break;
1744    
1745     default:
1746     break;
1747     }
1748     return(NULL);
1749     }
1750    
1751     /* rehash()
1752     *
1753     * Actual REHASH service routine. Called with sig == 0 if it has been called
1754     * as a result of an operator issuing this command, else assume it has been
1755     * called as a result of the server receiving a HUP signal.
1756     */
1757     int
1758     rehash(int sig)
1759     {
1760     if (sig != 0)
1761     sendto_realops_flags(UMODE_ALL, L_ALL,
1762     "Got signal SIGHUP, reloading ircd.conf file");
1763    
1764     #ifndef _WIN32
1765     restart_resolver();
1766     #endif
1767     /* don't close listeners until we know we can go ahead with the rehash */
1768    
1769     /* Check to see if we magically got(or lost) IPv6 support */
1770     check_can_use_v6();
1771    
1772     read_conf_files(0);
1773    
1774     if (ServerInfo.description != NULL)
1775     strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1776    
1777     #ifndef STATIC_MODULES
1778     load_conf_modules();
1779     #endif
1780    
1781     flush_deleted_I_P();
1782    
1783     rehashed_klines = 1;
1784    
1785     if (ConfigLoggingEntry.use_logging)
1786     reopen_log(logFileName);
1787    
1788     return(0);
1789     }
1790    
1791     /* set_default_conf()
1792     *
1793     * inputs - NONE
1794     * output - NONE
1795     * side effects - Set default values here.
1796     * This is called **PRIOR** to parsing the
1797     * configuration file. If you want to do some validation
1798     * of values later, put them in validate_conf().
1799     */
1800     static void
1801     set_default_conf(void)
1802     {
1803     /* verify init_class() ran, this should be an unnecessary check
1804     * but its not much work.
1805     */
1806     assert(class_default == (struct ConfItem *) class_items.tail->data);
1807    
1808     #ifdef HAVE_LIBCRYPTO
1809     ServerInfo.rsa_private_key = NULL;
1810     ServerInfo.rsa_private_key_file = NULL;
1811     #endif
1812    
1813     /* ServerInfo.name is not rehashable */
1814     /* ServerInfo.name = ServerInfo.name; */
1815     ServerInfo.description = NULL;
1816     DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1817     DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1818    
1819     memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1820     ServerInfo.specific_ipv4_vhost = 0;
1821     memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
1822     ServerInfo.specific_ipv6_vhost = 0;
1823    
1824     ServerInfo.max_clients = MAXCLIENTS_MAX;
1825 michael 956
1826     ServerInfo.hub = 0;
1827     delete_capability("HUB");
1828 adx 30 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 michael 948 unsigned int
2948 adx 30 get_sendq(struct Client *client_p)
2949     {
2950 michael 948 unsigned int sendq = DEFAULT_SENDQ;
2951 adx 30 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 db 936 * this allows use of parse_a_line in unkline etc.
3283 adx 30 *
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