ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1618
Committed: Tue Oct 30 21:04:38 2012 UTC (13 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 91772 byte(s)
Log Message:
- Made m_globops() and ms_globops() use sendto_realops_flags()
- Added message-type parameter to sendto_realops_flags() which can be one of
  SEND_NOTICE, SEND_GLOBAL, SEND_LOCOPS
- Forward-port -r1617

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

Properties

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