ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1123
Committed: Sun Feb 6 21:57:50 2011 UTC (14 years, 6 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.3/src/s_conf.c
File size: 99166 byte(s)
Log Message:
- Got rid of irc_addrinfo.c and irc_getnameinfo.c
- Fixed broken ipv6 detection due to incorrect use of AC_CHECK_TYPES

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

Properties

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