ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1417
Committed: Sat May 26 11:51:19 2012 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 93520 byte(s)
Log Message:
- "STATS Y|y" now reports CIDR limits as well

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

Properties

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