ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1364
Committed: Sun Apr 22 19:28:21 2012 UTC (13 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 99475 byte(s)
Log Message:
- Optimize get_oper_name(). No need to walk client_p->localClient->confs.
  If there's any attached CONF_OPERATOR, it'll always be the last attached
  one

File Contents

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

Properties

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