ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1388
Committed: Tue May 1 11:59:09 2012 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 94005 byte(s)
Log Message:
- conf.c:get_sendq(): fixed an assert()

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

Properties

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