ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1381
Committed: Tue May 1 08:21:27 2012 UTC (13 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 95695 byte(s)
Log Message:
- conf.c: remove CLIENT_CONF leftovers in clear_out_old_conf()
  clear_out_address_conf() already does the deal.

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 == XLINE_TYPE ||
2506     conf->type == RXLINE_TYPE ||
2507     conf->type == RKLINE_TYPE)
2508     {
2509     /* temporary (r)xlines are also on
2510     * the (r)xconf items list */
2511     if (conf->flags & CONF_FLAGS_TEMPORARY)
2512     continue;
2513    
2514     delete_conf_item(conf);
2515     }
2516     else
2517     {
2518     if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2519     {
2520 michael 671 match_item = map_to_conf(conf);
2521     if (match_item->ref_count <= 0)
2522 adx 30 delete_conf_item(conf);
2523     else
2524     {
2525     match_item->illegal = 1;
2526     dlinkDelete(&conf->node, *iterator);
2527     }
2528     }
2529     else
2530     delete_conf_item(conf);
2531     }
2532     }
2533     }
2534    
2535 michael 671 /*
2536     * don't delete the class table, rather mark all entries
2537 adx 30 * for deletion. The table is cleaned up by check_class. - avalon
2538     */
2539     DLINK_FOREACH(ptr, class_items.head)
2540     {
2541 michael 671 cltmp = map_to_conf(ptr->data);
2542    
2543 adx 30 if (ptr != class_items.tail) /* never mark the "default" class */
2544 michael 671 cltmp->active = 0;
2545 adx 30 }
2546    
2547     clear_out_address_conf();
2548    
2549     /* clean out module paths */
2550     mod_clear_paths();
2551    
2552     /* clean out ServerInfo */
2553     MyFree(ServerInfo.description);
2554     ServerInfo.description = NULL;
2555     MyFree(ServerInfo.network_name);
2556     ServerInfo.network_name = NULL;
2557     MyFree(ServerInfo.network_desc);
2558     ServerInfo.network_desc = NULL;
2559     MyFree(ConfigFileEntry.egdpool_path);
2560     ConfigFileEntry.egdpool_path = NULL;
2561     #ifdef HAVE_LIBCRYPTO
2562     if (ServerInfo.rsa_private_key != NULL)
2563     {
2564     RSA_free(ServerInfo.rsa_private_key);
2565     ServerInfo.rsa_private_key = NULL;
2566     }
2567    
2568     MyFree(ServerInfo.rsa_private_key_file);
2569     ServerInfo.rsa_private_key_file = NULL;
2570 michael 1316
2571     if (ServerInfo.server_ctx)
2572     SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
2573     SSL_OP_NO_SSLv3|
2574     SSL_OP_NO_TLSv1);
2575     if (ServerInfo.client_ctx)
2576     SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
2577     SSL_OP_NO_SSLv3|
2578     SSL_OP_NO_TLSv1);
2579 adx 30 #endif
2580    
2581     /* clean out old resvs from the conf */
2582     clear_conf_resv();
2583    
2584     /* clean out AdminInfo */
2585     MyFree(AdminInfo.name);
2586     AdminInfo.name = NULL;
2587     MyFree(AdminInfo.email);
2588     AdminInfo.email = NULL;
2589     MyFree(AdminInfo.description);
2590     AdminInfo.description = NULL;
2591    
2592     /* operator{} and class{} blocks are freed above */
2593     /* clean out listeners */
2594     close_listeners();
2595    
2596     /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2597     * exempt{} and gecos{} blocks are freed above too
2598     */
2599    
2600     /* clean out general */
2601 michael 1157 MyFree(ConfigFileEntry.service_name);
2602     ConfigFileEntry.service_name = NULL;
2603    
2604 adx 30 delete_isupport("INVEX");
2605     delete_isupport("EXCEPTS");
2606     }
2607    
2608     /* flush_deleted_I_P()
2609     *
2610     * inputs - none
2611     * output - none
2612     * side effects - This function removes I/P conf items
2613     */
2614     static void
2615     flush_deleted_I_P(void)
2616     {
2617     dlink_node *ptr;
2618     dlink_node *next_ptr;
2619     struct ConfItem *conf;
2620     struct AccessItem *aconf;
2621     dlink_list * free_items [] = {
2622 db 151 &server_items, &oconf_items, NULL
2623 adx 30 };
2624     dlink_list ** iterator = free_items; /* C is dumb */
2625    
2626     /* flush out deleted I and P lines
2627     * although still in use.
2628     */
2629     for (; *iterator != NULL; iterator++)
2630     {
2631     DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2632     {
2633     conf = ptr->data;
2634     aconf = (struct AccessItem *)map_to_conf(conf);
2635    
2636     if (IsConfIllegal(aconf))
2637     {
2638     dlinkDelete(ptr, *iterator);
2639    
2640     if (aconf->clients == 0)
2641     delete_conf_item(conf);
2642     }
2643     }
2644     }
2645     }
2646    
2647     /* get_conf_name()
2648     *
2649     * inputs - type of conf file to return name of file for
2650     * output - pointer to filename for type of conf
2651     * side effects - none
2652     */
2653     const char *
2654     get_conf_name(ConfType type)
2655     {
2656     switch (type)
2657     {
2658     case CONF_TYPE:
2659     return ConfigFileEntry.configfile;
2660     break;
2661     case KLINE_TYPE:
2662     return ConfigFileEntry.klinefile;
2663     break;
2664     case RKLINE_TYPE:
2665     return ConfigFileEntry.rklinefile;
2666     break;
2667     case DLINE_TYPE:
2668     return ConfigFileEntry.dlinefile;
2669     break;
2670     case XLINE_TYPE:
2671     return ConfigFileEntry.xlinefile;
2672     break;
2673     case RXLINE_TYPE:
2674     return ConfigFileEntry.rxlinefile;
2675     break;
2676     case CRESV_TYPE:
2677     return ConfigFileEntry.cresvfile;
2678     break;
2679     case NRESV_TYPE:
2680     return ConfigFileEntry.nresvfile;
2681     break;
2682     case GLINE_TYPE:
2683     return ConfigFileEntry.glinefile;
2684     break;
2685    
2686     default:
2687     return NULL; /* This should NEVER HAPPEN since we call this function
2688     only with the above values, this will cause us to core
2689     at some point if this happens so we know where it was */
2690     }
2691     }
2692    
2693     #define BAD_PING (-1)
2694    
2695     /* get_conf_ping()
2696     *
2697     * inputs - pointer to struct AccessItem
2698     * - pointer to a variable that receives ping warning time
2699     * output - ping frequency
2700     * side effects - NONE
2701     */
2702     static int
2703     get_conf_ping(struct ConfItem *conf, int *pingwarn)
2704     {
2705     struct ClassItem *aclass;
2706     struct AccessItem *aconf;
2707    
2708     if (conf != NULL)
2709     {
2710     aconf = (struct AccessItem *)map_to_conf(conf);
2711     if (aconf->class_ptr != NULL)
2712     {
2713     aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2714 michael 1377 *pingwarn = aclass->ping_warning;
2715     return aclass->ping_freq;
2716 adx 30 }
2717     }
2718    
2719     return BAD_PING;
2720     }
2721    
2722     /* get_client_class()
2723     *
2724     * inputs - pointer to client struct
2725     * output - pointer to name of class
2726     * side effects - NONE
2727     */
2728     const char *
2729     get_client_class(struct Client *target_p)
2730     {
2731     dlink_node *ptr;
2732     struct ConfItem *conf;
2733     struct AccessItem *aconf;
2734    
2735     if (target_p != NULL && !IsMe(target_p) &&
2736     target_p->localClient->confs.head != NULL)
2737     {
2738     DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2739     {
2740     conf = ptr->data;
2741    
2742     if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2743     conf->type == OPER_TYPE)
2744     {
2745     aconf = (struct AccessItem *) map_to_conf(conf);
2746     if (aconf->class_ptr != NULL)
2747     return aconf->class_ptr->name;
2748     }
2749     }
2750     }
2751    
2752     return "default";
2753     }
2754    
2755     /* get_client_ping()
2756     *
2757     * inputs - pointer to client struct
2758     * - pointer to a variable that receives ping warning time
2759     * output - ping frequency
2760     * side effects - NONE
2761     */
2762     int
2763     get_client_ping(struct Client *target_p, int *pingwarn)
2764     {
2765     int ping;
2766     struct ConfItem *conf;
2767     dlink_node *nlink;
2768    
2769     if (target_p->localClient->confs.head != NULL)
2770     DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2771     {
2772     conf = nlink->data;
2773    
2774     if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2775     (conf->type == OPER_TYPE))
2776     {
2777     ping = get_conf_ping(conf, pingwarn);
2778     if (ping > 0)
2779     return ping;
2780     }
2781     }
2782    
2783     *pingwarn = 0;
2784     return DEFAULT_PINGFREQUENCY;
2785     }
2786    
2787     /* find_class()
2788     *
2789     * inputs - string name of class
2790     * output - corresponding Class pointer
2791     * side effects - NONE
2792     */
2793     struct ConfItem *
2794     find_class(const char *classname)
2795     {
2796     struct ConfItem *conf;
2797    
2798 michael 1285 if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2799 michael 671 return conf;
2800 adx 30
2801     return class_default;
2802     }
2803    
2804     /* check_class()
2805     *
2806     * inputs - NONE
2807     * output - NONE
2808     * side effects -
2809     */
2810     void
2811     check_class(void)
2812     {
2813 michael 671 dlink_node *ptr = NULL, *next_ptr = NULL;
2814 adx 30
2815     DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2816     {
2817 michael 671 struct ClassItem *aclass = map_to_conf(ptr->data);
2818 adx 30
2819 michael 1377 if (!aclass->active && !aclass->curr_user_count)
2820 adx 30 {
2821     destroy_cidr_class(aclass);
2822 michael 673 delete_conf_item(ptr->data);
2823 adx 30 }
2824     }
2825     }
2826    
2827     /* init_class()
2828     *
2829     * inputs - NONE
2830     * output - NONE
2831     * side effects -
2832     */
2833     void
2834     init_class(void)
2835     {
2836     struct ClassItem *aclass;
2837    
2838     class_default = make_conf_item(CLASS_TYPE);
2839 michael 671
2840     aclass = map_to_conf(class_default);
2841     aclass->active = 1;
2842 adx 30 DupString(class_default->name, "default");
2843 michael 1377 aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
2844     aclass->ping_freq = DEFAULT_PINGFREQUENCY;
2845     aclass->max_total = MAXIMUM_LINKS_DEFAULT;
2846     aclass->max_sendq = DEFAULT_SENDQ;
2847 adx 30
2848     client_check_cb = register_callback("check_client", check_client);
2849     }
2850    
2851     /* get_sendq()
2852     *
2853     * inputs - pointer to client
2854     * output - sendq for this client as found from its class
2855     * side effects - NONE
2856     */
2857 michael 948 unsigned int
2858 adx 30 get_sendq(struct Client *client_p)
2859     {
2860 michael 948 unsigned int sendq = DEFAULT_SENDQ;
2861 adx 30 dlink_node *ptr;
2862     struct ConfItem *conf;
2863     struct ConfItem *class_conf;
2864     struct ClassItem *aclass;
2865     struct AccessItem *aconf;
2866    
2867     if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2868     {
2869     DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2870     {
2871     conf = ptr->data;
2872     if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2873     || (conf->type == CLIENT_TYPE))
2874     {
2875     aconf = (struct AccessItem *)map_to_conf(conf);
2876     if ((class_conf = aconf->class_ptr) == NULL)
2877     continue;
2878     aclass = (struct ClassItem *)map_to_conf(class_conf);
2879 michael 1377 sendq = aclass->max_sendq;
2880 adx 30 return sendq;
2881     }
2882     }
2883     }
2884     /* XXX return a default?
2885     * if here, then there wasn't an attached conf with a sendq
2886     * that is very bad -Dianora
2887     */
2888     return DEFAULT_SENDQ;
2889     }
2890    
2891     /* conf_add_class_to_conf()
2892     *
2893     * inputs - pointer to config item
2894     * output - NONE
2895     * side effects - Add a class pointer to a conf
2896     */
2897     void
2898     conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
2899     {
2900 michael 671 struct AccessItem *aconf = map_to_conf(conf);
2901     struct ClassItem *class = NULL;
2902 adx 30
2903     if (class_name == NULL)
2904     {
2905     aconf->class_ptr = class_default;
2906 michael 671
2907 adx 30 if (conf->type == CLIENT_TYPE)
2908     sendto_realops_flags(UMODE_ALL, L_ALL,
2909     "Warning *** Defaulting to default class for %s@%s",
2910     aconf->user, aconf->host);
2911     else
2912     sendto_realops_flags(UMODE_ALL, L_ALL,
2913     "Warning *** Defaulting to default class for %s",
2914     conf->name);
2915     }
2916     else
2917     aconf->class_ptr = find_class(class_name);
2918    
2919 michael 671 if (aconf->class_ptr)
2920     class = map_to_conf(aconf->class_ptr);
2921    
2922     if (aconf->class_ptr == NULL || !class->active)
2923 adx 30 {
2924     if (conf->type == CLIENT_TYPE)
2925     sendto_realops_flags(UMODE_ALL, L_ALL,
2926     "Warning *** Defaulting to default class for %s@%s",
2927     aconf->user, aconf->host);
2928     else
2929     sendto_realops_flags(UMODE_ALL, L_ALL,
2930     "Warning *** Defaulting to default class for %s",
2931     conf->name);
2932     aconf->class_ptr = class_default;
2933     }
2934     }
2935    
2936     /* conf_add_server()
2937     *
2938     * inputs - pointer to config item
2939     * - pointer to link count already on this conf
2940     * output - NONE
2941     * side effects - Add a connect block
2942     */
2943     int
2944 michael 593 conf_add_server(struct ConfItem *conf, const char *class_name)
2945 adx 30 {
2946 michael 1366 struct AccessItem *aconf = map_to_conf(conf);
2947 adx 30
2948     conf_add_class_to_conf(conf, class_name);
2949    
2950 michael 593 if (!aconf->host || !conf->name)
2951 adx 30 {
2952     sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
2953 michael 1247 ilog(LOG_TYPE_IRCD, "Bad connect block");
2954 adx 30 return -1;
2955     }
2956    
2957 michael 1302 if (EmptyString(aconf->passwd))
2958 adx 30 {
2959     sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
2960     conf->name);
2961 michael 1247 ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
2962 adx 30 return -1;
2963     }
2964    
2965     lookup_confhost(conf);
2966    
2967     return 0;
2968     }
2969    
2970     /* yyerror()
2971     *
2972     * inputs - message from parser
2973     * output - NONE
2974     * side effects - message to opers and log file entry is made
2975     */
2976     void
2977     yyerror(const char *msg)
2978     {
2979     char newlinebuf[IRCD_BUFSIZE];
2980    
2981 michael 967 if (conf_parser_ctx.pass != 1)
2982 adx 30 return;
2983    
2984     strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
2985     sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
2986     conffilebuf, lineno + 1, msg, newlinebuf);
2987 michael 1247 ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
2988 adx 30 conffilebuf, lineno + 1, msg, newlinebuf);
2989     }
2990    
2991     /*
2992     * valid_tkline()
2993     *
2994     * inputs - pointer to ascii string to check
2995     * - whether the specified time is in seconds or minutes
2996     * output - -1 not enough parameters
2997     * - 0 if not an integer number, else the number
2998     * side effects - none
2999     * Originally written by Dianora (Diane, db@db.net)
3000     */
3001     time_t
3002 michael 1120 valid_tkline(const char *p, int minutes)
3003 adx 30 {
3004     time_t result = 0;
3005    
3006 michael 1120 for (; *p; ++p)
3007 adx 30 {
3008 michael 1120 if (!IsDigit(*p))
3009 michael 1121 return 0;
3010 michael 1120
3011     result *= 10;
3012     result += ((*p) & 0xF);
3013 adx 30 }
3014    
3015 michael 1120 /*
3016     * In the degenerate case where oper does a /quote kline 0 user@host :reason
3017 adx 30 * i.e. they specifically use 0, I am going to return 1 instead
3018     * as a return value of non-zero is used to flag it as a temporary kline
3019     */
3020     if (result == 0)
3021     result = 1;
3022    
3023     /*
3024     * If the incoming time is in seconds convert it to minutes for the purpose
3025     * of this calculation
3026     */
3027     if (!minutes)
3028     result = result / (time_t)60;
3029    
3030     if (result > MAX_TDKLINE_TIME)
3031     result = MAX_TDKLINE_TIME;
3032    
3033     result = result * (time_t)60; /* turn it into seconds */
3034    
3035     return result;
3036     }
3037    
3038     /* valid_wild_card()
3039     *
3040     * input - pointer to client
3041     * - int flag, 0 for no warning oper 1 for warning oper
3042     * - count of following varargs to check
3043     * output - 0 if not valid, 1 if valid
3044     * side effects - NOTICE is given to source_p if warn is 1
3045     */
3046     int
3047     valid_wild_card(struct Client *source_p, int warn, int count, ...)
3048     {
3049     char *p;
3050     char tmpch;
3051     int nonwild = 0;
3052     va_list args;
3053    
3054     /*
3055     * Now we must check the user and host to make sure there
3056     * are at least NONWILDCHARS non-wildcard characters in
3057     * them, otherwise assume they are attempting to kline
3058     * *@* or some variant of that. This code will also catch
3059     * people attempting to kline *@*.tld, as long as NONWILDCHARS
3060     * is greater than 3. In that case, there are only 3 non-wild
3061     * characters (tld), so if NONWILDCHARS is 4, the kline will
3062     * be disallowed.
3063     * -wnder
3064     */
3065    
3066     va_start(args, count);
3067    
3068     while (count--)
3069     {
3070     p = va_arg(args, char *);
3071     if (p == NULL)
3072     continue;
3073    
3074     while ((tmpch = *p++))
3075     {
3076     if (!IsKWildChar(tmpch))
3077     {
3078     /*
3079     * If we find enough non-wild characters, we can
3080     * break - no point in searching further.
3081     */
3082     if (++nonwild >= ConfigFileEntry.min_nonwildcard)
3083     return 1;
3084     }
3085     }
3086     }
3087    
3088     if (warn)
3089     sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
3090     me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
3091     return 0;
3092     }
3093    
3094     /* XXX should this go into a separate file ? -Dianora */
3095     /* parse_aline
3096     *
3097     * input - pointer to cmd name being used
3098     * - pointer to client using cmd
3099     * - parc parameter count
3100     * - parv[] list of parameters to parse
3101     * - parse_flags bit map of things to test
3102     * - pointer to user or string to parse into
3103     * - pointer to host or NULL to parse into if non NULL
3104     * - pointer to optional tkline time or NULL
3105     * - pointer to target_server to parse into if non NULL
3106     * - pointer to reason to parse into
3107     *
3108     * output - 1 if valid, -1 if not valid
3109     * side effects - A generalised k/d/x etc. line parser,
3110     * "ALINE [time] user@host|string [ON] target :reason"
3111     * will parse returning a parsed user, host if
3112     * h_p pointer is non NULL, string otherwise.
3113     * if tkline_time pointer is non NULL a tk line will be set
3114     * to non zero if found.
3115     * if tkline_time pointer is NULL and tk line is found,
3116     * error is reported.
3117     * if target_server is NULL and an "ON" is found error
3118     * is reported.
3119     * if reason pointer is NULL ignore pointer,
3120 db 936 * this allows use of parse_a_line in unkline etc.
3121 adx 30 *
3122     * - Dianora
3123     */
3124     int
3125     parse_aline(const char *cmd, struct Client *source_p,
3126     int parc, char **parv,
3127     int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
3128     char **target_server, char **reason)
3129     {
3130     int found_tkline_time=0;
3131     static char def_reason[] = "No Reason";
3132     static char user[USERLEN*4+1];
3133     static char host[HOSTLEN*4+1];
3134    
3135     parv++;
3136     parc--;
3137    
3138     found_tkline_time = valid_tkline(*parv, TK_MINUTES);
3139    
3140     if (found_tkline_time != 0)
3141     {
3142     parv++;
3143     parc--;
3144    
3145     if (tkline_time != NULL)
3146     *tkline_time = found_tkline_time;
3147     else
3148     {
3149     sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3150     me.name, source_p->name, cmd);
3151     return -1;
3152     }
3153     }
3154    
3155     if (parc == 0)
3156     {
3157     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3158     me.name, source_p->name, cmd);
3159     return -1;
3160     }
3161    
3162     if (h_p == NULL)
3163     *up_p = *parv;
3164     else
3165     {
3166     if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
3167     return -1;
3168    
3169     *up_p = user;
3170     *h_p = host;
3171     }
3172    
3173     parc--;
3174     parv++;
3175    
3176     if (parc != 0)
3177     {
3178     if (irccmp(*parv, "ON") == 0)
3179     {
3180     parc--;
3181     parv++;
3182    
3183     if (target_server == NULL)
3184     {
3185     sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
3186     me.name, source_p->name, cmd);
3187     return -1;
3188     }
3189    
3190 michael 1219 if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
3191 adx 30 {
3192     sendto_one(source_p, form_str(ERR_NOPRIVS),
3193     me.name, source_p->name, "remoteban");
3194     return -1;
3195     }
3196    
3197     if (parc == 0 || EmptyString(*parv))
3198     {
3199     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3200     me.name, source_p->name, cmd);
3201     return -1;
3202     }
3203    
3204     *target_server = *parv;
3205     parc--;
3206     parv++;
3207     }
3208     else
3209     {
3210     /* Make sure target_server *is* NULL if no ON server found
3211     * caller probably NULL'd it first, but no harm to do it again -db
3212     */
3213     if (target_server != NULL)
3214     *target_server = NULL;
3215     }
3216     }
3217    
3218     if (h_p != NULL)
3219     {
3220     if (strchr(user, '!') != NULL)
3221     {
3222     sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3223     me.name, source_p->name);
3224     return -1;
3225     }
3226    
3227 michael 1243 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 2, *up_p, *h_p))
3228 adx 30 return -1;
3229     }
3230     else
3231 michael 1243 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 1, *up_p))
3232 adx 30 return -1;
3233    
3234     if (reason != NULL)
3235     {
3236 michael 867 if (parc != 0 && !EmptyString(*parv))
3237 adx 30 {
3238     *reason = *parv;
3239 michael 1243 if (!valid_comment(source_p, *reason, 1))
3240 adx 30 return -1;
3241     }
3242     else
3243     *reason = def_reason;
3244     }
3245    
3246     return 1;
3247     }
3248    
3249     /* find_user_host()
3250     *
3251     * inputs - pointer to client placing kline
3252     * - pointer to user_host_or_nick
3253     * - pointer to user buffer
3254     * - pointer to host buffer
3255     * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
3256     * side effects -
3257     */
3258     static int
3259     find_user_host(struct Client *source_p, char *user_host_or_nick,
3260     char *luser, char *lhost, unsigned int flags)
3261     {
3262     struct Client *target_p = NULL;
3263     char *hostp = NULL;
3264    
3265     if (lhost == NULL)
3266     {
3267     strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
3268     return 1;
3269     }
3270    
3271     if ((hostp = strchr(user_host_or_nick, '@')) || *user_host_or_nick == '*')
3272     {
3273     /* Explicit user@host mask given */
3274    
3275 michael 593 if (hostp != NULL) /* I'm a little user@host */
3276 adx 30 {
3277     *(hostp++) = '\0'; /* short and squat */
3278     if (*user_host_or_nick)
3279     strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
3280     else
3281     strcpy(luser, "*");
3282     if (*hostp)
3283     strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
3284     else
3285     strcpy(lhost, "*");
3286     }
3287     else
3288     {
3289     luser[0] = '*'; /* no @ found, assume its *@somehost */
3290     luser[1] = '\0';
3291     strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
3292     }
3293    
3294     return 1;
3295     }
3296     else if (!(flags & NOUSERLOOKUP))
3297     {
3298     /* Try to find user@host mask from nick */
3299     /* Okay to use source_p as the first param, because source_p == client_p */
3300     if ((target_p =
3301     find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
3302     return 0;
3303    
3304     if (IsExemptKline(target_p))
3305     {
3306     if (!IsServer(source_p))
3307     sendto_one(source_p,
3308     ":%s NOTICE %s :%s is E-lined",
3309     me.name, source_p->name, target_p->name);
3310     return 0;
3311     }
3312    
3313     /*
3314     * turn the "user" bit into "*user", blow away '~'
3315     * if found in original user name (non-idented)
3316     */
3317     strlcpy(luser, target_p->username, USERLEN*4 + 1);
3318    
3319     if (target_p->username[0] == '~')
3320     luser[0] = '*';
3321    
3322     if (target_p->sockhost[0] == '\0' ||
3323     (target_p->sockhost[0] == '0' && target_p->sockhost[1] == '\0'))
3324     strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
3325     else
3326     strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
3327     return 1;
3328     }
3329    
3330     return 0;
3331     }
3332    
3333     /* valid_comment()
3334     *
3335     * inputs - pointer to client
3336     * - pointer to comment
3337     * output - 0 if no valid comment,
3338     * - 1 if valid
3339     * side effects - truncates reason where necessary
3340     */
3341     int
3342     valid_comment(struct Client *source_p, char *comment, int warn)
3343     {
3344     if (strchr(comment, '"'))
3345     {
3346     if (warn)
3347     sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3348     me.name, source_p->name);
3349     return 0;
3350     }
3351    
3352     if (strlen(comment) > REASONLEN)
3353     comment[REASONLEN-1] = '\0';
3354    
3355     return 1;
3356     }
3357    
3358     /* match_conf_password()
3359     *
3360     * inputs - pointer to given password
3361     * - pointer to Conf
3362     * output - 1 or 0 if match
3363     * side effects - none
3364     */
3365     int
3366     match_conf_password(const char *password, const struct AccessItem *aconf)
3367     {
3368     const char *encr = NULL;
3369    
3370     if (password == NULL || aconf->passwd == NULL)
3371     return 0;
3372    
3373     if (aconf->flags & CONF_FLAGS_ENCRYPTED)
3374     {
3375     /* use first two chars of the password they send in as salt */
3376     /* If the password in the conf is MD5, and ircd is linked
3377     * to scrypt on FreeBSD, or the standard crypt library on
3378     * glibc Linux, then this code will work fine on generating
3379     * the proper encrypted hash for comparison.
3380     */
3381     if (*aconf->passwd)
3382     encr = crypt(password, aconf->passwd);
3383     else
3384     encr = "";
3385     }
3386     else
3387     encr = password;
3388    
3389     return !strcmp(encr, aconf->passwd);
3390     }
3391    
3392     /*
3393     * cluster_a_line
3394     *
3395     * inputs - client sending the cluster
3396     * - command name "KLINE" "XLINE" etc.
3397     * - capab -- CAP_KLN etc. from s_serv.h
3398 michael 1309 * - cluster type -- CLUSTER_KLINE etc. from conf.h
3399 adx 30 * - pattern and args to send along
3400     * output - none
3401     * side effects - Take source_p send the pattern with args given
3402     * along to all servers that match capab and cluster type
3403     */
3404     void
3405     cluster_a_line(struct Client *source_p, const char *command,
3406 michael 593 int capab, int cluster_type, const char *pattern, ...)
3407 adx 30 {
3408     va_list args;
3409     char buffer[IRCD_BUFSIZE];
3410 michael 593 const dlink_node *ptr = NULL;
3411 adx 30
3412     va_start(args, pattern);
3413     vsnprintf(buffer, sizeof(buffer), pattern, args);
3414     va_end(args);
3415    
3416     DLINK_FOREACH(ptr, cluster_items.head)
3417     {
3418 michael 593 const struct ConfItem *conf = ptr->data;
3419 adx 30
3420     if (conf->flags & cluster_type)
3421     sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
3422     "%s %s %s", command, conf->name, buffer);
3423     }
3424     }
3425    
3426     /*
3427     * split_nuh
3428     *
3429     * inputs - pointer to original mask (modified in place)
3430     * - pointer to pointer where nick should go
3431     * - pointer to pointer where user should go
3432     * - pointer to pointer where host should go
3433     * output - NONE
3434     * side effects - mask is modified in place
3435     * If nick pointer is NULL, ignore writing to it
3436     * this allows us to use this function elsewhere.
3437     *
3438     * mask nick user host
3439     * ---------------------- ------- ------- ------
3440     * Dianora!db@db.net Dianora db db.net
3441     * Dianora Dianora * *
3442     * db.net * * db.net
3443     * OR if nick pointer is NULL
3444     * Dianora - * Dianora
3445     * Dianora! Dianora * *
3446     * Dianora!@ Dianora * *
3447     * Dianora!db Dianora db *
3448     * Dianora!@db.net Dianora * db.net
3449     * db@db.net * db db.net
3450     * !@ * * *
3451     * @ * * *
3452     * ! * * *
3453     */
3454     void
3455 michael 593 split_nuh(struct split_nuh_item *const iptr)
3456 adx 30 {
3457     char *p = NULL, *q = NULL;
3458    
3459 michael 593 if (iptr->nickptr)
3460     strlcpy(iptr->nickptr, "*", iptr->nicksize);
3461     if (iptr->userptr)
3462     strlcpy(iptr->userptr, "*", iptr->usersize);
3463     if (iptr->hostptr)
3464     strlcpy(iptr->hostptr, "*", iptr->hostsize);
3465    
3466     if ((p = strchr(iptr->nuhmask, '!')))
3467 adx 30 {
3468     *p = '\0';
3469    
3470 michael 593 if (iptr->nickptr && *iptr->nuhmask != '\0')
3471     strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3472 adx 30
3473 michael 593 if ((q = strchr(++p, '@'))) {
3474     *q++ = '\0';
3475    
3476 adx 30 if (*p != '\0')
3477 michael 593 strlcpy(iptr->userptr, p, iptr->usersize);
3478 adx 30
3479 michael 593 if (*q != '\0')
3480     strlcpy(iptr->hostptr, q, iptr->hostsize);
3481 adx 30 }
3482     else
3483     {
3484     if (*p != '\0')
3485 michael 593 strlcpy(iptr->userptr, p, iptr->usersize);
3486 adx 30 }
3487     }
3488 michael 593 else
3489 adx 30 {
3490 michael 593 /* No ! found so lets look for a user@host */
3491     if ((p = strchr(iptr->nuhmask, '@')))
3492 adx 30 {
3493 michael 593 /* if found a @ */
3494     *p++ = '\0';
3495 adx 30
3496 michael 593 if (*iptr->nuhmask != '\0')
3497     strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
3498 adx 30
3499 michael 593 if (*p != '\0')
3500     strlcpy(iptr->hostptr, p, iptr->hostsize);
3501 adx 30 }
3502 michael 593 else
3503 adx 30 {
3504 michael 593 /* no @ found */
3505     if (!iptr->nickptr || strpbrk(iptr->nuhmask, ".:"))
3506     strlcpy(iptr->hostptr, iptr->nuhmask, iptr->hostsize);
3507 adx 30 else
3508 michael 593 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3509 adx 30 }
3510     }
3511     }
3512    
3513     /*
3514     * flags_to_ascii
3515     *
3516     * inputs - flags is a bitmask
3517     * - pointer to table of ascii letters corresponding
3518     * to each bit
3519     * - flag 1 for convert ToLower if bit missing
3520     * 0 if ignore.
3521     * output - none
3522     * side effects - string pointed to by p has bitmap chars written to it
3523     */
3524     static void
3525     flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3526     int lowerit)
3527     {
3528     unsigned int mask = 1;
3529     int i = 0;
3530    
3531     for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3532     {
3533     if (flags & mask)
3534     *p++ = bit_table[i];
3535 michael 593 else if (lowerit)
3536 adx 30 *p++ = ToLower(bit_table[i]);
3537     }
3538     *p = '\0';
3539     }
3540    
3541     /*
3542     * cidr_limit_reached
3543     *
3544     * inputs - int flag allowing over_rule of limits
3545     * - pointer to the ip to be added
3546     * - pointer to the class
3547     * output - non zero if limit reached
3548     * 0 if limit not reached
3549     * side effects -
3550     */
3551     static int
3552     cidr_limit_reached(int over_rule,
3553     struct irc_ssaddr *ip, struct ClassItem *aclass)
3554     {
3555     dlink_node *ptr = NULL;
3556     struct CidrItem *cidr;
3557    
3558 michael 1377 if (aclass->number_per_cidr <= 0)
3559 adx 30 return 0;
3560    
3561     if (ip->ss.ss_family == AF_INET)
3562     {
3563 michael 1377 if (aclass->cidr_bitlen_ipv4 <= 0)
3564 adx 30 return 0;
3565    
3566     DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3567     {
3568     cidr = ptr->data;
3569 michael 1377 if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3570 adx 30 {
3571 michael 1377 if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3572 adx 30 return -1;
3573     cidr->number_on_this_cidr++;
3574     return 0;
3575     }
3576     }
3577     cidr = MyMalloc(sizeof(struct CidrItem));
3578     cidr->number_on_this_cidr = 1;
3579     cidr->mask = *ip;
3580 michael 1377 mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv4);
3581 adx 30 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3582     }
3583     #ifdef IPV6
3584 michael 1377 else if (aclass->cidr_bitlen_ipv6 > 0)
3585 adx 30 {
3586     DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3587     {
3588     cidr = ptr->data;
3589 michael 1377 if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3590 adx 30 {
3591 michael 1377 if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3592 adx 30 return -1;
3593     cidr->number_on_this_cidr++;
3594     return 0;
3595     }
3596     }
3597     cidr = MyMalloc(sizeof(struct CidrItem));
3598     cidr->number_on_this_cidr = 1;
3599     cidr->mask = *ip;
3600 michael 1377 mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv6);
3601 adx 30 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3602     }
3603     #endif
3604     return 0;
3605     }
3606    
3607     /*
3608     * remove_from_cidr_check
3609     *
3610     * inputs - pointer to the ip to be removed
3611     * - pointer to the class
3612     * output - NONE
3613     * side effects -
3614     */
3615     static void
3616     remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3617     {
3618     dlink_node *ptr = NULL;
3619     dlink_node *next_ptr = NULL;
3620     struct CidrItem *cidr;
3621    
3622 michael 1377 if (aclass->number_per_cidr == 0)
3623 adx 30 return;
3624    
3625     if (ip->ss.ss_family == AF_INET)
3626     {
3627 michael 1377 if (aclass->cidr_bitlen_ipv4 <= 0)
3628 adx 30 return;
3629    
3630     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3631     {
3632     cidr = ptr->data;
3633 michael 1377 if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3634 adx 30 {
3635     cidr->number_on_this_cidr--;
3636     if (cidr->number_on_this_cidr == 0)
3637     {
3638     dlinkDelete(ptr, &aclass->list_ipv4);
3639     MyFree(cidr);
3640     return;
3641     }
3642     }
3643     }
3644     }
3645     #ifdef IPV6
3646 michael 1377 else if (aclass->cidr_bitlen_ipv6 > 0)
3647 adx 30 {
3648     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3649     {
3650     cidr = ptr->data;
3651 michael 1377 if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3652 adx 30 {
3653     cidr->number_on_this_cidr--;
3654     if (cidr->number_on_this_cidr == 0)
3655     {
3656     dlinkDelete(ptr, &aclass->list_ipv6);
3657     MyFree(cidr);
3658     return;
3659     }
3660     }
3661     }
3662     }
3663     #endif
3664     }
3665    
3666     static void
3667     rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3668     dlink_list *old_list, dlink_list *new_list, int changed)
3669     {
3670     dlink_node *ptr;
3671     struct Client *client_p;
3672     struct ConfItem *conf;
3673     struct AccessItem *aconf;
3674    
3675     if (!changed)
3676     {
3677     *new_list = *old_list;
3678     old_list->head = old_list->tail = NULL;
3679     old_list->length = 0;
3680     return;
3681     }
3682    
3683     DLINK_FOREACH(ptr, local_client_list.head)
3684     {
3685     client_p = ptr->data;
3686     if (client_p->localClient->aftype != aftype)
3687     continue;
3688     if (dlink_list_length(&client_p->localClient->confs) == 0)
3689     continue;
3690    
3691     conf = client_p->localClient->confs.tail->data;
3692     if (conf->type == CLIENT_TYPE)
3693     {
3694     aconf = map_to_conf(conf);
3695     if (aconf->class_ptr == oldcl)
3696     cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3697     }
3698     }
3699     }
3700    
3701     /*
3702     * rebuild_cidr_class
3703     *
3704     * inputs - pointer to old conf
3705     * - pointer to new_class
3706     * output - none
3707     * side effects - rebuilds the class link list of cidr blocks
3708     */
3709     void
3710     rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3711     {
3712     struct ClassItem *old_class = map_to_conf(conf);
3713    
3714 michael 1377 if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
3715 adx 30 {
3716 michael 1377 if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
3717 adx 30 rebuild_cidr_list(AF_INET, conf, new_class,
3718     &old_class->list_ipv4, &new_class->list_ipv4,
3719 michael 1377 old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
3720 adx 30
3721     #ifdef IPV6
3722 michael 1377 if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
3723 adx 30 rebuild_cidr_list(AF_INET6, conf, new_class,
3724     &old_class->list_ipv6, &new_class->list_ipv6,
3725 michael 1377 old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
3726 adx 30 #endif
3727     }
3728    
3729     destroy_cidr_class(old_class);
3730     }
3731    
3732     /*
3733     * destroy_cidr_list
3734     *
3735     * inputs - pointer to class dlink list of cidr blocks
3736     * output - none
3737     * side effects - completely destroys the class link list of cidr blocks
3738     */
3739     static void
3740     destroy_cidr_list(dlink_list *list)
3741     {
3742 michael 671 dlink_node *ptr = NULL, *next_ptr = NULL;
3743 adx 30
3744     DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3745     {
3746     dlinkDelete(ptr, list);
3747 michael 671 MyFree(ptr->data);
3748 adx 30 }
3749     }
3750    
3751     /*
3752     * destroy_cidr_class
3753     *
3754     * inputs - pointer to class
3755     * output - none
3756     * side effects - completely destroys the class link list of cidr blocks
3757     */
3758     static void
3759     destroy_cidr_class(struct ClassItem *aclass)
3760     {
3761     destroy_cidr_list(&aclass->list_ipv4);
3762     destroy_cidr_list(&aclass->list_ipv6);
3763     }

Properties

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