ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/conf.c
Revision: 1363
Committed: Sun Apr 22 19:15:48 2012 UTC (11 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 99481 byte(s)
Log Message:
- conf.c: remove unused prototypes

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

Properties

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