ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1157
Committed: Tue Aug 9 22:03:59 2011 UTC (14 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/s_conf.c
File size: 100223 byte(s)
Log Message:
- preliminary services support

File Contents

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

Properties

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