ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1413
Committed: Sat May 26 08:25:12 2012 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 93372 byte(s)
Log Message:
- Don't try to access aconf->user when aconf is a SERVER_TYPE.
  aconf->user is a NULL pointer.

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

Properties

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