ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1394
Committed: Wed May 2 19:29:19 2012 UTC (11 years, 10 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 93518 byte(s)
Log Message:
- conf.c:attach_conf(): remove useless conftype test.
  conf is now always one of CLIENT_TYPE, SERVER_TYPE,
  or OPER_TYPE.

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

Properties

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