ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1432
Committed: Sat Jun 9 19:40:08 2012 UTC (11 years, 10 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 93561 byte(s)
Log Message:
- Added channel::max_chans_per_oper configuration directive. The old way
  was to let ircops join three times the amount of max_chans_per_user.

  I'd rather would make this a class{} based limit, but this would require us
  to reprint the ISUPPORT buffer every time a client connects.

File Contents

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

Properties

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