ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1368
Committed: Wed Apr 25 16:42:06 2012 UTC (11 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 98276 byte(s)
Log Message:
- Remove temporary RKLINES/RXLINES leftovers

File Contents

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

Properties

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