ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 433
Committed: Sat Feb 11 15:22:07 2006 UTC (19 years, 6 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 101545 byte(s)
Log Message:
- Don't try to keep pointers to already freed memory on temporary_resv list
  when manually removing tempoary N/C resvs.

File Contents

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

Properties

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