ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1377
Committed: Mon Apr 30 19:35:16 2012 UTC (11 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 95886 byte(s)
Log Message:
- Remove all Class related #defines like MaxTotal, MaxSendq, etc.
  All they do is lead to confusion.

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

Properties

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