ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/s_conf.c
Revision: 140
Committed: Sun Oct 16 06:09:42 2005 UTC (20 years, 9 months ago) by db
Content type: text/x-csrc
File size: 75098 byte(s)
Log Message:
- removed free_access_item()
- a few cleanups in s_conf.h as well


File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * s_conf.c: Configuration file functions.
4     *
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     #include "ircd_defs.h"
27     #include "s_conf.h"
28 db 101 #include "parse_aline.h"
29 adx 30 #include "s_serv.h"
30     #include "resv.h"
31     #include "s_stats.h"
32     #include "channel.h"
33     #include "client.h"
34     #include "common.h"
35     #include "hash.h"
36     #include "ircd.h"
37     #include "listener.h"
38     #include "hostmask.h"
39     #include "modules.h"
40     #include "numeric.h"
41     #include "send.h"
42     #include "s_gline.h"
43     #include "userhost.h"
44     #include "s_user.h"
45     #include "channel_mode.h"
46    
47     struct Callback *client_check_cb = NULL;
48     struct config_server_hide ConfigServerHide;
49    
50     /* general conf items link list root, other than k lines etc. */
51     dlink_list server_items = { NULL, NULL, 0 };
52     dlink_list cluster_items = { NULL, NULL, 0 };
53     dlink_list hub_items = { NULL, NULL, 0 };
54     dlink_list leaf_items = { NULL, NULL, 0 };
55     dlink_list oconf_items = { NULL, NULL, 0 };
56     dlink_list uconf_items = { NULL, NULL, 0 };
57     dlink_list xconf_items = { NULL, NULL, 0 };
58     dlink_list rxconf_items = { NULL, NULL, 0 };
59     dlink_list rkconf_items = { NULL, NULL, 0 };
60     dlink_list nresv_items = { NULL, NULL, 0 };
61     dlink_list class_items = { NULL, NULL, 0 };
62     dlink_list gdeny_items = { NULL, NULL, 0 };
63    
64 db 131 extern unsigned int lineno;
65     extern char linebuf[];
66     extern char conffilebuf[IRCD_BUFSIZE];
67     extern char yytext[];
68     extern int yyparse(); /* defined in y.tab.c */
69     unsigned int scount = 0; /* used by yyparse(), etc */
70     int ypass = 1; /* used by yyparse() */
71    
72     /* internally defined functions */
73     static void lookup_confhost(struct ConfItem *);
74     static void set_default_conf(void);
75     static void validate_conf(void);
76     static void read_conf(FBFILE *);
77     static void clear_out_old_conf(void);
78     static void flush_deleted_I_P(void);
79     static void garbage_collect_ip_entries(void);
80     static int hash_ip(struct irc_ssaddr *);
81     static int verify_access(struct Client *, const char *, struct AccessItem **);
82     static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
83     static void parse_conf_file(int, int);
84     static int check_class_limits(struct Client *, int ,struct ClassItem *);
85     static int attach_class(struct Client *client_p, struct ClassItem *aclass);
86     static void free_aconf_items(struct ConfItem *, dlink_list *);
87     static void free_match_items(struct ConfItem *, dlink_list *);
88     static void delete_link(struct ConfItem *, dlink_list *);
89    
90 db 139 #define CONFSIZE (offsetof(struct ConfItem, conf))
91 db 128 struct conf_item_table_type conf_item_table[] =
92     {
93     /* CONF_TYPE */
94 db 131 { 0, 0 , 0, 0},
95 db 128 /* CLASS_TYPE */
96 db 139 { CONFSIZE + sizeof(struct ClassItem), 0,
97 db 131 &class_items, delete_link},
98 db 128 /* OPER_TYPE */
99 db 139 { CONFSIZE + sizeof(struct AccessItem), CONF_OPERATOR,
100 db 131 &oconf_items, free_aconf_items },
101 db 128 /* CLIENT_TYPE */
102 db 139 { CONFSIZE + sizeof(struct AccessItem), CONF_CLIENT,
103 db 131 NULL, free_aconf_items },
104 db 128 /* SERVER_TYPE */
105 db 139 { CONFSIZE + sizeof(struct AccessItem), CONF_SERVER,
106 db 131 &server_items, free_aconf_items },
107 db 128 /* HUB_TYPE */
108 db 139 { CONFSIZE + sizeof(struct MatchItem), 0,
109 db 131 &hub_items, free_match_items },
110 db 128 /* LEAF_TYPE */
111 db 139 { CONFSIZE + sizeof(struct MatchItem), 0,
112 db 131 &leaf_items, free_match_items },
113 db 128 /* KLINE_TYPE */
114 db 139 { CONFSIZE + sizeof(struct AccessItem), CONF_KLINE,
115 db 131 NULL, free_aconf_items },
116 db 128 /* DLINE_TYPE */
117 db 139 { CONFSIZE + sizeof(struct AccessItem), CONF_DLINE,
118 db 131 NULL, free_aconf_items },
119 db 128 /* EXEMPTDLINE_TYPE */
120 db 139 { CONFSIZE + sizeof(struct AccessItem), CONF_EXEMPTDLINE,
121 db 131 NULL, free_aconf_items },
122 db 128 /* CLUSTER_TYPE */
123 db 139 { CONFSIZE , 0,
124 db 131 &cluster_items, delete_link },
125 db 128 /* RKLINE_TYPE */
126 db 139 { CONFSIZE + sizeof(struct AccessItem), CONF_KLINE,
127 db 131 &rkconf_items, free_aconf_items },
128 db 128 /* RXLINE_TYPE */
129 db 139 { CONFSIZE + sizeof(struct MatchItem), CONF_KLINE,
130 db 131 &rxconf_items, free_match_items },
131 db 128 /* XLINE_TYPE */
132 db 139 { CONFSIZE + sizeof(struct AccessItem), 0,
133 db 131 &xconf_items, free_match_items },
134 db 128 /* ULINE_TYPE */
135 db 139 { CONFSIZE + sizeof(struct AccessItem), 0,
136 db 131 &uconf_items, free_match_items },
137 db 128 /* GLINE_TYPE */
138 db 139 { CONFSIZE + sizeof(struct AccessItem), CONF_GLINE,
139 db 131 NULL, free_aconf_items },
140 db 128 /* CRESV_TYPE */
141 db 139 { CONFSIZE + sizeof(struct MatchItem), 0, NULL },
142 db 128 /* NRESV_TYPE */
143 db 139 { CONFSIZE + sizeof(struct MatchItem), 0,
144 db 131 &nresv_items, free_match_items },
145 db 128 /* GDENY_TYPE */
146 db 139 { CONFSIZE + sizeof(struct AccessItem), 0,
147 db 131 &gdeny_items, free_aconf_items },
148 db 128 { 0, 0, 0}
149     };
150 adx 30
151     /*
152     * bit_len
153     */
154     static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
155     static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
156     static void destroy_cidr_class(struct ClassItem *);
157    
158     static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
159    
160     FBFILE *conf_fbfile_in = NULL;
161    
162     /* address of default class conf */
163     static struct ConfItem *class_default;
164    
165     /* usually, with hash tables, you use a prime number...
166     * but in this case I am dealing with ip addresses,
167     * not ascii strings.
168     */
169     #define IP_HASH_SIZE 0x1000
170    
171     struct ip_entry
172     {
173     struct irc_ssaddr ip;
174     int count;
175     time_t last_attempt;
176     struct ip_entry *next;
177     };
178    
179     static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
180     static BlockHeap *ip_entry_heap = NULL;
181     static int ip_entries_count = 0;
182    
183     /* conf_dns_callback()
184     *
185     * inputs - pointer to struct AccessItem
186     * - pointer to DNSReply reply
187     * output - none
188     * side effects - called when resolver query finishes
189     * if the query resulted in a successful search, hp will contain
190     * a non-null pointer, otherwise hp will be null.
191     * if successful save hp in the conf item it was called with
192     */
193     static void
194     conf_dns_callback(void *vptr, struct DNSReply *reply)
195     {
196     struct AccessItem *aconf = (struct AccessItem *)vptr;
197     struct ConfItem *conf;
198    
199     MyFree(aconf->dns_query);
200     aconf->dns_query = NULL;
201    
202     if (reply != NULL)
203     memcpy(&aconf->ipnum, &reply->addr, sizeof(reply->addr));
204 db 131 else
205     {
206 adx 30 ilog(L_NOTICE, "Host not found: %s, ignoring connect{} block",
207     aconf->host);
208 db 139 conf = aconf->conf;
209 adx 30 sendto_realops_flags(UMODE_ALL, L_ALL,
210     "Ignoring connect{} block for %s - host not found",
211     conf->name);
212     delete_conf_item(conf);
213     }
214     }
215    
216     /* conf_dns_lookup()
217     *
218     * do a nameserver lookup of the conf host
219     * if the conf entry is currently doing a ns lookup do nothing, otherwise
220     * allocate a dns_query and start ns lookup.
221     */
222     static void
223     conf_dns_lookup(struct AccessItem *aconf)
224     {
225     if (aconf->dns_query == NULL)
226     {
227     aconf->dns_query = MyMalloc(sizeof(struct DNSQuery));
228     aconf->dns_query->ptr = aconf;
229     aconf->dns_query->callback = conf_dns_callback;
230     gethost_byname(aconf->host, aconf->dns_query);
231     }
232     }
233    
234     /* make_conf_item()
235     *
236     * inputs - type of item
237     * output - pointer to new conf entry
238     * side effects - none
239     */
240     struct ConfItem *
241     make_conf_item(ConfType type)
242     {
243 db 128 size_t size;
244 adx 30 struct ConfItem *conf = NULL;
245     struct AccessItem *aconf = NULL;
246 db 128 dlink_list *list;
247     int status;
248 adx 30
249 db 128 size = conf_item_table[type].size;
250     conf = MyMalloc(size);
251     conf->type = type;
252     list = conf_item_table[type].list;
253     status = conf_item_table[type].status;
254 db 139 /* XXX conf is in the same place in each subtype */
255     aconf = &conf->conf.AccessItem;
256     aconf->conf = conf;
257     /* XXX */
258 db 128 if (status != 0)
259 adx 30 {
260 db 128 aconf->status = status;
261 adx 30 aconf->aftype = AF_INET;
262     }
263 db 128 if (list != NULL)
264     dlinkAdd(conf, &conf->node, list);
265 adx 30
266 db 128 return conf;
267 adx 30 }
268    
269 db 131 /*
270     * delete_conf_item
271     *
272     * inputs - pointer to struct ConfItem
273     * output - NONE
274     * side effects - Take given conf and delete it.
275     */
276 adx 30 void
277     delete_conf_item(struct ConfItem *conf)
278     {
279     ConfType type = conf->type;
280 db 130 dlink_list *list;
281 adx 30
282 db 130 list = conf_item_table[type].list;
283    
284 adx 30 MyFree(conf->name);
285     conf->name = NULL;
286 db 131 MyFree(conf->regexpname);
287     conf->regexpname = NULL;
288 adx 30
289 db 131 if (conf_item_table[type].freer != NULL)
290     conf_item_table[type].freer(conf, list);
291 adx 30
292 db 131 MyFree(conf);
293 adx 30 }
294    
295 db 130 /*
296     * free_aconf_items
297     *
298 db 131 * inputs - pointer to struct ConfItem
299     * - pointer to list to delink from, if NULL nothing to do
300 db 130 * output - NONE
301 db 131 * side effects - free all AcessItem entries, optionally delink from
302     * given list
303 db 130 */
304     static void
305 db 131 free_aconf_items(struct ConfItem *conf, dlink_list *list)
306 db 130 {
307 db 131 struct AccessItem *aconf;
308    
309 db 139 aconf = &conf->conf.AccessItem;
310 db 131
311 db 130 if (aconf->dns_query != NULL)
312     {
313     delete_resolver_queries(aconf->dns_query);
314     MyFree(aconf->dns_query);
315     }
316     if (aconf->passwd != NULL)
317     memset(aconf->passwd, 0, strlen(aconf->passwd));
318     if (aconf->spasswd != NULL)
319     memset(aconf->spasswd, 0, strlen(aconf->spasswd));
320     aconf->class_ptr = NULL;
321 db 126
322 db 130 MyFree(aconf->regexuser);
323     MyFree(aconf->regexhost);
324     MyFree(aconf->passwd);
325     MyFree(aconf->spasswd);
326     MyFree(aconf->reason);
327     MyFree(aconf->oper_reason);
328     MyFree(aconf->user);
329     MyFree(aconf->host);
330     MyFree(aconf->fakename);
331     #ifdef HAVE_LIBCRYPTO
332     if (aconf->rsa_public_key)
333     RSA_free(aconf->rsa_public_key);
334     MyFree(aconf->rsa_public_key_file);
335     #endif
336 db 131
337     if (list != NULL && !IsConfIllegal(aconf))
338     dlinkDelete(&conf->node, list);
339 db 130 }
340    
341 db 131 /*
342     * delete_link
343     *
344     * inputs - pointer to struct ConfItem
345     * - pointer to list
346     * output - NONE
347     * side effects - Simply unhook given ConfItem from given list
348     */
349     static void
350     delete_link(struct ConfItem *conf, dlink_list *list)
351 db 130 {
352 db 131 if (list != NULL)
353     dlinkDelete(&conf->node, list);
354     }
355    
356    
357     /*
358     * free_match_items
359     *
360     * inputs - pointer to struct ConfItem
361     * - pointer to list to delink from, if NULL nothing to do
362     * output - NONE
363     * side effects - free all MatchItem entries, optionally delink from
364     * given list
365     */
366     static void
367     free_match_items(struct ConfItem *conf, dlink_list *list)
368     {
369     struct MatchItem *match_item;
370    
371 db 139 match_item = &conf->conf.MatchItem;
372 db 130 MyFree(match_item->user);
373     MyFree(match_item->host);
374     MyFree(match_item->reason);
375     MyFree(match_item->oper_reason);
376 db 131 if ((list != NULL) && !match_item->illegal)
377     dlinkDelete(&conf->node, list);
378 db 130 }
379    
380 adx 30 static const unsigned int shared_bit_table[] =
381     { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
382    
383     /* report_confitem_types()
384     *
385 db 131 * inputs - pointer to client requesting confitem report
386     * - ConfType to report
387     * output - none
388     * side effects - report conf items to source_p
389 adx 30 */
390     void
391     report_confitem_types(struct Client *source_p, ConfType type, int temp)
392     {
393     dlink_node *ptr = NULL;
394     struct ConfItem *conf = NULL;
395     struct AccessItem *aconf = NULL;
396     struct MatchItem *matchitem = NULL;
397     struct ClassItem *classitem = NULL;
398     char buf[12];
399     char *p = NULL;
400    
401     switch (type)
402     {
403     case GDENY_TYPE:
404     DLINK_FOREACH(ptr, gdeny_items.head)
405     {
406     conf = ptr->data;
407 db 139 aconf = &conf->conf.AccessItem;
408 adx 30
409     p = buf;
410    
411     if (aconf->flags & GDENY_BLOCK)
412     *p++ = 'B';
413     else
414     *p++ = 'b';
415    
416     if (aconf->flags & GDENY_REJECT)
417     *p++ = 'R';
418     else
419     *p++ = 'r';
420    
421     *p = '\0';
422    
423     sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
424     me.name, RPL_STATSDEBUG, source_p->name,
425     aconf->user, aconf->host, conf->name, buf);
426     }
427     break;
428    
429     case XLINE_TYPE:
430     DLINK_FOREACH(ptr, xconf_items.head)
431     {
432     conf = ptr->data;
433 db 139 matchitem = &conf->conf.MatchItem;
434 adx 30
435     sendto_one(source_p, form_str(RPL_STATSXLINE),
436     me.name, source_p->name,
437     matchitem->hold ? "x": "X", matchitem->count,
438     conf->name, matchitem->reason);
439     }
440     break;
441    
442     case RXLINE_TYPE:
443     DLINK_FOREACH(ptr, rxconf_items.head)
444     {
445     conf = ptr->data;
446 db 139 matchitem = &conf->conf.MatchItem;
447 adx 30
448     sendto_one(source_p, form_str(RPL_STATSXLINE),
449     me.name, source_p->name,
450     matchitem->hold ? "xR": "XR", matchitem->count,
451     conf->name, matchitem->reason);
452     }
453     break;
454    
455     case RKLINE_TYPE:
456     p = temp ? "Rk" : "RK";
457    
458     DLINK_FOREACH(ptr, rkconf_items.head)
459     {
460 db 139 aconf = &((struct ConfItem *)(conf = ptr->data))->conf.AccessItem;
461 adx 30
462     if (temp && !(conf->flags & CONF_FLAGS_TEMPORARY))
463     continue;
464    
465     sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
466     source_p->name, p, aconf->host, aconf->user,
467     aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
468     }
469     break;
470    
471     case ULINE_TYPE:
472     DLINK_FOREACH(ptr, uconf_items.head)
473     {
474     conf = ptr->data;
475 db 139 matchitem = &conf->conf.MatchItem;
476 adx 30
477     p = buf;
478    
479     /* some of these are redundant for the sake of
480     * consistency with cluster{} flags
481     */
482     *p++ = 'c';
483     flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
484    
485     sendto_one(source_p, form_str(RPL_STATSULINE),
486     me.name, source_p->name, conf->name,
487     matchitem->user?matchitem->user: "*",
488     matchitem->host?matchitem->host: "*", buf);
489     }
490    
491     DLINK_FOREACH(ptr, cluster_items.head)
492     {
493     conf = ptr->data;
494    
495     p = buf;
496    
497     *p++ = 'C';
498     flags_to_ascii(conf->flags, shared_bit_table, p, 0);
499    
500     sendto_one(source_p, form_str(RPL_STATSULINE),
501     me.name, source_p->name, conf->name,
502     "*", "*", buf);
503     }
504    
505     break;
506    
507     case OPER_TYPE:
508     DLINK_FOREACH(ptr, oconf_items.head)
509     {
510     conf = ptr->data;
511 db 139 aconf = &conf->conf.AccessItem;
512 adx 30
513     /* Don't allow non opers to see oper privs */
514     if (IsOper(source_p))
515     sendto_one(source_p, form_str(RPL_STATSOLINE),
516     me.name, source_p->name, 'O', aconf->user, aconf->host,
517     conf->name, oper_privs_as_string(aconf->port),
518     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
519     else
520     sendto_one(source_p, form_str(RPL_STATSOLINE),
521     me.name, source_p->name, 'O', aconf->user, aconf->host,
522     conf->name, "0",
523     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
524     }
525     break;
526    
527     case CLASS_TYPE:
528     DLINK_FOREACH(ptr, class_items.head)
529     {
530     conf = ptr->data;
531 db 139 classitem = &conf->conf.ClassItem;
532 adx 30 sendto_one(source_p, form_str(RPL_STATSYLINE),
533     me.name, source_p->name, 'Y',
534     conf->name, PingFreq(classitem),
535     ConFreq(classitem),
536     MaxTotal(classitem), MaxSendq(classitem));
537     }
538     break;
539    
540     case CONF_TYPE:
541     case CLIENT_TYPE:
542     break;
543    
544     case SERVER_TYPE:
545     DLINK_FOREACH(ptr, server_items.head)
546     {
547     p = buf;
548    
549     conf = ptr->data;
550 db 139 aconf = &conf->conf.AccessItem;
551 adx 30
552     buf[0] = '\0';
553    
554     if (IsConfAllowAutoConn(aconf))
555     *p++ = 'A';
556     if (IsConfCryptLink(aconf))
557     *p++ = 'C';
558     if (IsConfLazyLink(aconf))
559     *p++ = 'L';
560     if (aconf->fakename)
561     *p++ = 'M';
562     if (IsConfTopicBurst(aconf))
563     *p++ = 'T';
564     if (IsConfCompressed(aconf))
565     *p++ = 'Z';
566     if (buf[0] == '\0')
567     *p++ = '*';
568    
569     *p = '\0';
570    
571     /* Allow admins to see actual ips
572     * unless hide_server_ips is enabled
573     */
574     if (!ConfigServerHide.hide_server_ips && IsAdmin(source_p))
575     sendto_one(source_p, form_str(RPL_STATSCLINE),
576     me.name, source_p->name, 'C', aconf->host,
577     buf, conf->name, aconf->port,
578     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
579     else
580     sendto_one(source_p, form_str(RPL_STATSCLINE),
581     me.name, source_p->name, 'C',
582     "*@127.0.0.1", buf, conf->name, aconf->port,
583     aconf->class_ptr ? aconf->class_ptr->name : "<default>");
584     }
585     break;
586    
587     case HUB_TYPE:
588     DLINK_FOREACH(ptr, hub_items.head)
589     {
590     conf = ptr->data;
591 db 139 matchitem = &conf->conf.MatchItem;
592 adx 30 sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
593     source_p->name, 'H', matchitem->host, conf->name, 0, "*");
594     }
595     break;
596    
597     case LEAF_TYPE:
598     DLINK_FOREACH(ptr, leaf_items.head)
599     {
600     conf = ptr->data;
601 db 139 matchitem = &conf->conf.MatchItem;
602 adx 30 sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
603     source_p->name, 'L', matchitem->host, conf->name, 0, "*");
604     }
605     break;
606    
607     case GLINE_TYPE:
608     case KLINE_TYPE:
609     case DLINE_TYPE:
610     case EXEMPTDLINE_TYPE:
611     case CRESV_TYPE:
612     case NRESV_TYPE:
613     case CLUSTER_TYPE:
614     break;
615     }
616     }
617    
618     /* check_client()
619     *
620 db 131 * inputs - pointer to client
621     * output - 0 = Success
622     * NOT_AUTHORIZED (-1) = Access denied (no I line match)
623     * IRCD_SOCKET_ERROR (-2) = Bad socket.
624     * I_LINE_FULL (-3) = I-line is full
625     * TOO_MANY (-4) = Too many connections from hostname
626     * BANNED_CLIENT (-5) = K-lined
627 adx 30 * side effects - Ordinary client access check.
628 db 131 * Look for conf lines which have the same
629     * status as the flags passed.
630 adx 30 */
631     static void *
632     check_client(va_list args)
633     {
634     struct Client *source_p = va_arg(args, struct Client *);
635     const char *username = va_arg(args, const char *);
636 michael 129 struct AccessItem **aptr = va_arg(args, struct AccessItem **);
637 adx 30 int i;
638    
639 michael 129 if ((i = verify_access(source_p, username, aptr)))
640 adx 30 ilog(L_INFO, "Access denied: %s[%s]",
641     source_p->name, source_p->sockhost);
642    
643     switch (i)
644     {
645     case IRCD_SOCKET_ERROR:
646     exit_client(source_p, &me, "Socket Error");
647     break;
648    
649     case TOO_MANY:
650     sendto_realops_flags(UMODE_FULL, L_ALL,
651     "Too many on IP for %s (%s).",
652     get_client_name(source_p, SHOW_IP),
653     source_p->sockhost);
654     ilog(L_INFO,"Too many connections on IP from %s.",
655     get_client_name(source_p, SHOW_IP));
656     ServerStats->is_ref++;
657     exit_client(source_p, &me, "No more connections allowed on that IP");
658     break;
659    
660     case I_LINE_FULL:
661     sendto_realops_flags(UMODE_FULL, L_ALL,
662     "I-line is full for %s (%s).",
663     get_client_name(source_p, SHOW_IP),
664     source_p->sockhost);
665     ilog(L_INFO,"Too many connections from %s.",
666     get_client_name(source_p, SHOW_IP));
667     ServerStats->is_ref++;
668     exit_client(source_p, &me,
669     "No more connections allowed in your connection class");
670     break;
671    
672     case NOT_AUTHORIZED:
673     {
674     static char ipaddr[HOSTIPLEN];
675     ServerStats->is_ref++;
676     /* jdc - lists server name & port connections are on */
677     /* a purely cosmetical change */
678     irc_getnameinfo((struct sockaddr*)&source_p->localClient->ip,
679     source_p->localClient->ip.ss_len, ipaddr, HOSTIPLEN, NULL, 0,
680     NI_NUMERICHOST);
681     sendto_realops_flags(UMODE_UNAUTH, L_ALL,
682     "Unauthorized client connection from %s [%s] on [%s/%u].",
683     get_client_name(source_p, SHOW_IP),
684     ipaddr,
685     source_p->localClient->listener->name,
686     source_p->localClient->listener->port);
687     ilog(L_INFO,
688     "Unauthorized client connection from %s on [%s/%u].",
689     get_client_name(source_p, SHOW_IP),
690     source_p->localClient->listener->name,
691     source_p->localClient->listener->port);
692    
693     /* XXX It is prolematical whether it is better to use the
694     * capture reject code here or rely on the connecting too fast code.
695     * - Dianora
696     */
697     if(REJECT_HOLD_TIME > 0)
698     {
699     sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
700     me.name, source_p->name);
701     source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
702     SetCaptured(source_p);
703     }
704     else
705     exit_client(source_p, &me, "You are not authorized to use this server");
706     break;
707     }
708    
709     case BANNED_CLIENT:
710     /*
711     * Don't exit them immediately, play with them a bit.
712     * - Dianora
713     */
714     if (REJECT_HOLD_TIME > 0)
715     {
716     source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
717     SetCaptured(source_p);
718     }
719     else
720     exit_client(source_p, &me, "Banned");
721     ServerStats->is_ref++;
722     break;
723    
724     case 0:
725     default:
726     break;
727     }
728    
729     return (i < 0 ? NULL : source_p);
730     }
731    
732     /* verify_access()
733     *
734 db 131 * inputs - pointer to client to verify
735     * - pointer to proposed username
736     * output - 0 if success -'ve if not
737     * side effect - find the first (best) I line to attach.
738 adx 30 */
739     static int
740 michael 129 verify_access(struct Client *client_p, const char *username, struct AccessItem **aptr)
741 adx 30 {
742     struct AccessItem *aconf = NULL, *rkconf = NULL;
743     struct ConfItem *conf = NULL;
744 db 126 struct ClassItem *aclass = NULL;
745 adx 30 char non_ident[USERLEN + 1] = { '~', '\0' };
746     const char *uhi[3];
747    
748     if (IsGotId(client_p))
749     {
750     aconf = find_address_conf(client_p->host, client_p->username,
751     &client_p->localClient->ip,
752     client_p->localClient->aftype,
753     client_p->localClient->passwd);
754     }
755     else
756     {
757     strlcpy(non_ident+1, username, sizeof(non_ident)-1);
758     aconf = find_address_conf(client_p->host,non_ident,
759     &client_p->localClient->ip,
760     client_p->localClient->aftype,
761     client_p->localClient->passwd);
762     }
763    
764     uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
765     uhi[1] = client_p->host;
766     uhi[2] = client_p->sockhost;
767    
768     rkconf = find_regexp_kline(uhi);
769    
770     if (aconf != NULL)
771     {
772     if (IsConfClient(aconf) && !rkconf)
773     {
774 db 139 conf = aconf->conf;
775 adx 30
776     if (IsConfRedir(aconf))
777     {
778     sendto_one(client_p, form_str(RPL_REDIR),
779     me.name, client_p->name,
780     conf->name ? conf->name : "",
781     aconf->port);
782     return(NOT_AUTHORIZED);
783     }
784    
785     if (IsConfDoIdentd(aconf))
786     SetNeedId(client_p);
787    
788     /* Thanks for spoof idea amm */
789     if (IsConfDoSpoofIp(aconf))
790     {
791     if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
792     sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
793     client_p->name, client_p->host, conf->name);
794     strlcpy(client_p->host, conf->name, sizeof(client_p->host));
795     SetIPSpoof(client_p);
796     }
797    
798 db 139 aclass = &((struct ConfItem *)(aconf->class_ptr))->conf.ClassItem;
799 db 126
800     if (check_class_limits(client_p, IsConfExemptLimits(aconf), aclass))
801     {
802 michael 129 assert(aptr);
803     *aptr = aconf;
804 db 128 aconf->clients++;
805 db 126 attach_class(client_p, aclass);
806     return(0);
807     }
808     else
809     return(TOO_MANY);
810 adx 30 }
811     else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
812     {
813     /* XXX */
814     aconf = rkconf ? rkconf : aconf;
815     if (IsConfGline(aconf))
816     sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
817     client_p->name);
818     if (ConfigFileEntry.kline_with_reason)
819     sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
820     me.name, client_p->name, aconf->reason);
821     return(BANNED_CLIENT);
822     }
823     }
824    
825     return(NOT_AUTHORIZED);
826     }
827    
828 db 126 /* check_class_limits()
829 adx 30 *
830 db 131 * inputs - client pointer
831     * - int exempt or not to limits
832     * - class pointer
833     * output - 0 if limits ok, non 0 if limits not ok
834 db 126 * side effects - NONE
835 adx 30 */
836 db 126 static int
837     check_class_limits(struct Client *client_p, int exempt,
838     struct ClassItem *aclass)
839 adx 30 {
840     struct ip_entry *ip_found;
841     int a_limit_reached = 0;
842     int local = 0, global = 0, ident = 0;
843    
844 db 126 ip_found = find_or_add_ip(&client_p->localClient->ip);
845     ip_found->count++;
846     SetIpHash(client_p);
847 adx 30
848 db 126 count_user_host(client_p->username, client_p->host,
849     &global, &local, &ident);
850 adx 30
851 db 126 /* XXX blah. go down checking the various silly limits
852     * setting a_limit_reached if any limit is reached.
853     * - Dianora
854     */
855     if (MaxTotal(aclass) != 0 && CurrUserCount(aclass) >= MaxTotal(aclass))
856     a_limit_reached = 1;
857     else if (MaxPerIp(aclass) != 0 && ip_found->count >= MaxPerIp(aclass))
858     a_limit_reached = 1;
859     else if (MaxLocal(aclass) != 0 && local >= MaxLocal(aclass))
860     a_limit_reached = 1;
861     else if (MaxGlobal(aclass) != 0 && global >= MaxGlobal(aclass))
862     a_limit_reached = 1;
863     else if (MaxIdent(aclass) != 0 && ident >= MaxIdent(aclass) &&
864     client_p->username[0] != '~')
865     a_limit_reached = 1;
866 adx 30
867 db 101
868 db 126 if (a_limit_reached)
869     {
870     if (!exempt)
871     return 0; /* Already at maximum allowed */
872 db 101
873 db 126 sendto_one(client_p,
874     ":%s NOTICE %s :*** Your connection class is full, "
875     "but you have exceed_limit = yes;", me.name, client_p->name);
876 db 101 }
877    
878 db 126 if (cidr_limit_reached(exempt, &client_p->localClient->ip, aclass))
879     return 0; /* Already at maximum allowed */
880 adx 30
881 db 126 return 1;
882 adx 30 }
883    
884     /* init_ip_hash_table()
885     *
886     * inputs - NONE
887     * output - NONE
888     * side effects - allocate memory for ip_entry(s)
889     * - clear the ip hash table
890     */
891     void
892     init_ip_hash_table(void)
893     {
894     ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
895     2 * hard_fdlimit);
896     memset(ip_hash_table, 0, sizeof(ip_hash_table));
897     }
898    
899     /* find_or_add_ip()
900     *
901     * inputs - pointer to struct irc_ssaddr
902     * output - pointer to a struct ip_entry
903     * side effects -
904     *
905     * If the ip # was not found, a new struct ip_entry is created, and the ip
906     * count set to 0.
907     */
908     static struct ip_entry *
909     find_or_add_ip(struct irc_ssaddr *ip_in)
910     {
911     struct ip_entry *ptr, *newptr;
912     int hash_index = hash_ip(ip_in), res;
913     struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
914     #ifdef IPV6
915     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
916     #endif
917    
918     for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
919     {
920     #ifdef IPV6
921     if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
922     continue;
923     if (ip_in->ss.ss_family == AF_INET6)
924     {
925     ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
926     res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
927     }
928     else
929     #endif
930     {
931     ptr_v4 = (struct sockaddr_in *)&ptr->ip;
932     res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
933     }
934     if (res == 0)
935     {
936     /* Found entry already in hash, return it. */
937     return ptr;
938     }
939     }
940    
941     if (ip_entries_count >= 2 * hard_fdlimit)
942     garbage_collect_ip_entries();
943    
944     newptr = BlockHeapAlloc(ip_entry_heap);
945     ip_entries_count++;
946     memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
947    
948     newptr->next = ip_hash_table[hash_index];
949     ip_hash_table[hash_index] = newptr;
950    
951     return newptr;
952     }
953    
954     /* remove_one_ip()
955     *
956     * inputs - unsigned long IP address value
957     * output - NONE
958     * side effects - The ip address given, is looked up in ip hash table
959     * and number of ip#'s for that ip decremented.
960     * If ip # count reaches 0 and has expired,
961     * the struct ip_entry is returned to the ip_entry_heap
962     */
963     void
964     remove_one_ip(struct irc_ssaddr *ip_in)
965     {
966     struct ip_entry *ptr;
967     struct ip_entry *last_ptr = NULL;
968     int hash_index = hash_ip(ip_in), res;
969     struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
970     #ifdef IPV6
971     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
972     #endif
973    
974     for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
975     {
976     #ifdef IPV6
977     if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
978     continue;
979     if (ip_in->ss.ss_family == AF_INET6)
980     {
981     ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
982     res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
983     }
984     else
985     #endif
986     {
987     ptr_v4 = (struct sockaddr_in *)&ptr->ip;
988     res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
989     }
990     if (res)
991     continue;
992     if (ptr->count > 0)
993     ptr->count--;
994     if (ptr->count == 0 &&
995     (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
996     {
997     if (last_ptr != NULL)
998     last_ptr->next = ptr->next;
999     else
1000     ip_hash_table[hash_index] = ptr->next;
1001    
1002     BlockHeapFree(ip_entry_heap, ptr);
1003     ip_entries_count--;
1004     return;
1005     }
1006     last_ptr = ptr;
1007     }
1008     }
1009    
1010     /* hash_ip()
1011     *
1012     * input - pointer to an irc_inaddr
1013     * output - integer value used as index into hash table
1014     * side effects - hopefully, none
1015     */
1016     static int
1017     hash_ip(struct irc_ssaddr *addr)
1018     {
1019     if (addr->ss.ss_family == AF_INET)
1020     {
1021     struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
1022     int hash;
1023     u_int32_t ip;
1024    
1025     ip = ntohl(v4->sin_addr.s_addr);
1026     hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
1027     return hash;
1028     }
1029     #ifdef IPV6
1030     else
1031     {
1032     int hash;
1033     struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
1034     u_int32_t *ip = (u_int32_t *)&v6->sin6_addr.s6_addr;
1035    
1036     hash = ip[0] ^ ip[3];
1037     hash ^= hash >> 16;
1038     hash ^= hash >> 8;
1039     hash = hash & (IP_HASH_SIZE - 1);
1040     return hash;
1041     }
1042     #else
1043     return 0;
1044     #endif
1045     }
1046    
1047     /* count_ip_hash()
1048     *
1049     * inputs - pointer to counter of number of ips hashed
1050     * - pointer to memory used for ip hash
1051     * output - returned via pointers input
1052     * side effects - NONE
1053     *
1054     * number of hashed ip #'s is counted up, plus the amount of memory
1055     * used in the hash.
1056     */
1057     void
1058     count_ip_hash(int *number_ips_stored, unsigned long *mem_ips_stored)
1059     {
1060     struct ip_entry *ptr;
1061     int i;
1062    
1063     *number_ips_stored = 0;
1064     *mem_ips_stored = 0;
1065    
1066     for (i = 0; i < IP_HASH_SIZE; i++)
1067     {
1068     for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
1069     {
1070     *number_ips_stored += 1;
1071     *mem_ips_stored += sizeof(struct ip_entry);
1072     }
1073     }
1074     }
1075    
1076     /* garbage_collect_ip_entries()
1077     *
1078     * input - NONE
1079     * output - NONE
1080     * side effects - free up all ip entries with no connections
1081     */
1082     static void
1083     garbage_collect_ip_entries(void)
1084     {
1085     struct ip_entry *ptr;
1086     struct ip_entry *last_ptr;
1087     struct ip_entry *next_ptr;
1088     int i;
1089    
1090     for (i = 0; i < IP_HASH_SIZE; i++)
1091     {
1092     last_ptr = NULL;
1093    
1094     for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
1095     {
1096     next_ptr = ptr->next;
1097    
1098     if (ptr->count == 0 &&
1099     (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1100     {
1101     if (last_ptr != NULL)
1102     last_ptr->next = ptr->next;
1103     else
1104     ip_hash_table[i] = ptr->next;
1105     BlockHeapFree(ip_entry_heap, ptr);
1106     ip_entries_count--;
1107     }
1108     else
1109     last_ptr = ptr;
1110     }
1111     }
1112     }
1113    
1114     /* detach_conf()
1115     *
1116     * inputs - pointer to client to detach
1117     * - type of conf to detach
1118     * output - 0 for success, -1 for failure
1119     * side effects - Disassociate configuration from the client.
1120     * Also removes a class from the list if marked for deleting.
1121     */
1122     int
1123     detach_conf(struct Client *client_p, ConfType type)
1124     {
1125     dlink_node *ptr, *next_ptr;
1126     struct ConfItem *conf;
1127     struct ClassItem *aclass;
1128     struct AccessItem *aconf;
1129     struct MatchItem *match_item;
1130    
1131 db 126 aclass = client_p->localClient->class;
1132     remove_from_cidr_check(&client_p->localClient->ip, aclass);
1133 db 101
1134 db 126 if (CurrUserCount(aclass) > 0)
1135     aclass->curr_user_count--;
1136     if (MaxTotal(aclass) < 0 && CurrUserCount(aclass) <= 0)
1137 db 139 delete_conf_item(aclass->conf);
1138 db 126
1139     /* More to do if this client is a server, else return */
1140     if (client_p->serv == NULL)
1141     return 0;
1142 db 101
1143 db 126 conf = client_p->serv->sconf;
1144 db 139 aconf = &conf->conf.AccessItem;
1145 db 101
1146 db 126 if (aconf->clients > 0)
1147     --aconf->clients;
1148     if (aconf->clients == 0 && IsConfIllegal(aconf))
1149     delete_conf_item(conf);
1150     client_p->serv->sconf = NULL;
1151 db 101
1152     DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->serv->leafs_hubs.head)
1153     {
1154 adx 30 conf = ptr->data;
1155 db 139 match_item = &conf->conf.MatchItem;
1156 adx 30
1157 db 126 dlinkDelete(ptr, &client_p->serv->leafs_hubs);
1158     free_dlink_node(ptr);
1159 adx 30
1160 db 126 if (match_item->ref_count == 0 && match_item->illegal)
1161     delete_conf_item(conf);
1162 adx 30 }
1163    
1164 db 126 return 0;
1165 adx 30 }
1166    
1167 db 101 /* attach_leaf_hub()
1168 adx 30 *
1169 db 101 * inputs - server pointer
1170     * - conf (HUB or LEAF mask) pointer
1171     * output - 0 if sucessfully added, 1 if unsuccessful.
1172 adx 30 * side effects - Associate a specific configuration entry to a *local*
1173 db 101 * server
1174 adx 30 */
1175     int
1176 db 101 attach_leaf_hub(struct Client *client_p, struct ConfItem *conf)
1177 adx 30 {
1178     struct MatchItem *match_item;
1179 db 101 if (dlinkFind(&client_p->serv->leafs_hubs, conf) != NULL)
1180     return 1;
1181 adx 30
1182 db 139 match_item = &conf->conf.MatchItem;
1183 db 101 match_item->ref_count++;
1184     dlinkAdd(conf, make_dlink_node(), &client_p->serv->leafs_hubs);
1185 adx 30
1186     return 0;
1187     }
1188    
1189 db 126 /*
1190     * attach_class
1191     *
1192     * inputs - pointer to client to attach ClassItem to
1193     * - pointer to aclass
1194     * output - 0 if successful, -1 if unsuccesful
1195     * side effects -
1196     */
1197     static int
1198     attach_class(struct Client *client_p, struct ClassItem *aclass)
1199     {
1200     if (client_p->localClient->class == NULL)
1201     {
1202     CurrUserCount(aclass)++;
1203     client_p->localClient->class = aclass;
1204     return 0;
1205     }
1206     else
1207     {
1208     ilog(L_ERROR, "%s: attach_class already attached",
1209     get_client_name(client_p, SHOW_IP));
1210     return -1;
1211     }
1212     }
1213    
1214     /*
1215     * attach_server_conf
1216     *
1217     * inputs - pointer to client to attach ConfItem to
1218     * - pointer to ConfItem
1219     * output - 0 if successful, -1 if unsuccesful
1220     * side effects -
1221     */
1222     int
1223     attach_server_conf(struct Client *client_p, struct ConfItem *conf)
1224     {
1225     if (client_p->serv->sconf == NULL)
1226     {
1227     client_p->serv->sconf = conf;
1228     return 0;
1229     }
1230     else
1231     {
1232     ilog(L_ERROR, "%s: attach_server_conf already attached",
1233     get_client_name(client_p, SHOW_IP));
1234     return -1;
1235     }
1236     }
1237    
1238 adx 30 /* attach_connect_block()
1239     *
1240     * inputs - pointer to server to attach
1241     * - name of server
1242     * - hostname of server
1243     * output - true (1) if both are found, otherwise return false (0)
1244     * side effects - find connect block and attach them to connecting client
1245     */
1246     int
1247     attach_connect_block(struct Client *client_p, const char *name,
1248     const char *host)
1249     {
1250     dlink_node *ptr;
1251     struct ConfItem *conf;
1252     struct AccessItem *aconf;
1253    
1254     assert(client_p != NULL);
1255     assert(host != NULL);
1256    
1257     if (client_p == NULL || host == NULL)
1258     return 0;
1259    
1260     DLINK_FOREACH(ptr, server_items.head)
1261     {
1262     conf = ptr->data;
1263 db 139 aconf = &conf->conf.AccessItem;
1264 adx 30
1265     if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
1266     continue;
1267    
1268 db 130 attach_server_conf(client_p, conf);
1269 db 126 return 1;
1270 adx 30 }
1271    
1272     return 0;
1273     }
1274    
1275     /* find_matching_name_conf()
1276     *
1277     * inputs - type of link list to look in
1278     * - pointer to name string to find
1279     * - pointer to user
1280     * - pointer to host
1281     * - optional action to match on as well
1282     * output - NULL or pointer to found struct MatchItem
1283     * side effects - looks for a match on name field
1284     */
1285     struct ConfItem *
1286     find_matching_name_conf(ConfType type, const char *name, const char *user,
1287     const char *host, int action)
1288     {
1289     dlink_node *ptr=NULL;
1290     struct ConfItem *conf=NULL;
1291     struct AccessItem *aconf=NULL;
1292     struct MatchItem *match_item=NULL;
1293 db 130 dlink_list *list_p = conf_item_table[type].list;
1294 adx 30
1295     switch (type)
1296     {
1297     case RXLINE_TYPE:
1298     DLINK_FOREACH(ptr, list_p->head)
1299     {
1300     conf = ptr->data;
1301     assert(conf->regexpname);
1302    
1303     if (!ircd_pcre_exec(conf->regexpname, name))
1304     return conf;
1305     }
1306     break;
1307    
1308     case XLINE_TYPE:
1309     case ULINE_TYPE:
1310     case NRESV_TYPE:
1311     DLINK_FOREACH(ptr, list_p->head)
1312     {
1313     conf = ptr->data;
1314    
1315 db 139 match_item = &conf->conf.MatchItem;
1316 adx 30 if (EmptyString(conf->name))
1317     continue;
1318     if ((name != NULL) && match_esc(conf->name, name))
1319     {
1320     if ((user == NULL && (host == NULL)))
1321     return conf;
1322     if ((match_item->action & action) != action)
1323     continue;
1324     if (EmptyString(match_item->user) || EmptyString(match_item->host))
1325     return conf;
1326     if (match(match_item->user, user) && match(match_item->host, host))
1327     return conf;
1328     }
1329     }
1330     break;
1331    
1332     case SERVER_TYPE:
1333     DLINK_FOREACH(ptr, list_p->head)
1334     {
1335     conf = ptr->data;
1336 db 139 aconf = &conf->conf.AccessItem;
1337 adx 30
1338     if ((name != NULL) && match_esc(name, conf->name))
1339     return conf;
1340     else if ((host != NULL) && match_esc(host, aconf->host))
1341     return conf;
1342     }
1343     break;
1344    
1345     default:
1346     break;
1347     }
1348     return NULL;
1349     }
1350    
1351     /* find_exact_name_conf()
1352     *
1353     * inputs - type of link list to look in
1354     * - pointer to name string to find
1355     * - pointer to user
1356     * - pointer to host
1357     * output - NULL or pointer to found struct MatchItem
1358     * side effects - looks for an exact match on name field
1359     */
1360     struct ConfItem *
1361     find_exact_name_conf(ConfType type, const char *name,
1362     const char *user, const char *host)
1363     {
1364     dlink_node *ptr = NULL;
1365     struct AccessItem *aconf;
1366     struct ConfItem *conf;
1367     struct MatchItem *match_item;
1368     dlink_list *list_p;
1369    
1370 db 130 list_p = conf_item_table[type].list;
1371 adx 30
1372     switch(type)
1373     {
1374     case RXLINE_TYPE:
1375     case XLINE_TYPE:
1376     case ULINE_TYPE:
1377     case NRESV_TYPE:
1378    
1379     DLINK_FOREACH(ptr, list_p->head)
1380     {
1381     conf = ptr->data;
1382 db 139 match_item = &conf->conf.MatchItem;
1383 adx 30 if (EmptyString(conf->name))
1384     continue;
1385    
1386     if (irccmp(conf->name, name) == 0)
1387     {
1388     if ((user == NULL && (host == NULL)))
1389     return (conf);
1390     if (EmptyString(match_item->user) || EmptyString(match_item->host))
1391     return (conf);
1392     if (match(match_item->user, user) && match(match_item->host, host))
1393     return (conf);
1394     }
1395     }
1396     break;
1397    
1398     case OPER_TYPE:
1399     DLINK_FOREACH(ptr, list_p->head)
1400     {
1401     conf = ptr->data;
1402 db 139 aconf = &conf->conf.AccessItem;
1403 adx 30 if (EmptyString(conf->name))
1404     continue;
1405    
1406     if (irccmp(conf->name, name) == 0)
1407     {
1408     if ((user == NULL && (host == NULL)))
1409     return (conf);
1410     if (EmptyString(aconf->user) || EmptyString(aconf->host))
1411     return (conf);
1412     if (match(aconf->user, user) && match(aconf->host, host))
1413     return (conf);
1414     }
1415     }
1416     break;
1417    
1418     case SERVER_TYPE:
1419     DLINK_FOREACH(ptr, list_p->head)
1420     {
1421     conf = ptr->data;
1422     if (EmptyString(conf->name))
1423     continue;
1424 db 139 aconf = &conf->conf.AccessItem;
1425 adx 30
1426     if (name == NULL)
1427     {
1428     if (EmptyString(aconf->host))
1429     continue;
1430     if (irccmp(aconf->host, host) == 0)
1431     return(conf);
1432     }
1433     else if (irccmp(conf->name, name) == 0)
1434     {
1435     return (conf);
1436     }
1437     }
1438     break;
1439    
1440     case CLASS_TYPE:
1441     DLINK_FOREACH(ptr, list_p->head)
1442     {
1443     conf = ptr->data;
1444     if (EmptyString(conf->name))
1445     continue;
1446    
1447     if (irccmp(conf->name, name) == 0)
1448     return (conf);
1449     }
1450     break;
1451    
1452     default:
1453     break;
1454     }
1455     return(NULL);
1456     }
1457    
1458     /* rehash()
1459     *
1460     * Actual REHASH service routine. Called with sig == 0 if it has been called
1461     * as a result of an operator issuing this command, else assume it has been
1462     * called as a result of the server receiving a HUP signal.
1463     */
1464     int
1465     rehash(int sig)
1466     {
1467     if (sig != 0)
1468     sendto_realops_flags(UMODE_ALL, L_ALL,
1469     "Got signal SIGHUP, reloading ircd.conf file");
1470    
1471     #ifndef _WIN32
1472     restart_resolver();
1473     #endif
1474 db 126 /* Don't close listeners until known I can go ahead with the rehash */
1475 adx 30
1476     /* Check to see if we magically got(or lost) IPv6 support */
1477 adx 68 ServerInfo.can_use_v6 = check_can_use_v6();
1478 adx 30
1479     read_conf_files(0);
1480    
1481     if (ServerInfo.description != NULL)
1482     strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1483    
1484     #ifndef STATIC_MODULES
1485     load_conf_modules();
1486     #endif
1487    
1488     flush_deleted_I_P();
1489    
1490     rehashed_klines = 1;
1491    
1492     if (ConfigLoggingEntry.use_logging)
1493     reopen_log(logFileName);
1494    
1495     return(0);
1496     }
1497    
1498     /* set_default_conf()
1499     *
1500     * inputs - NONE
1501     * output - NONE
1502     * side effects - Set default values here.
1503     * This is called **PRIOR** to parsing the
1504     * configuration file. If you want to do some validation
1505     * of values later, put them in validate_conf().
1506     */
1507     static void
1508     set_default_conf(void)
1509     {
1510     /* verify init_class() ran, this should be an unnecessary check
1511     * but its not much work.
1512     */
1513     assert(class_default == (struct ConfItem *) class_items.tail->data);
1514    
1515     #ifdef HAVE_LIBCRYPTO
1516     ServerInfo.rsa_private_key = NULL;
1517     ServerInfo.rsa_private_key_file = NULL;
1518     #endif
1519    
1520     /* ServerInfo.name is not rehashable */
1521     /* ServerInfo.name = ServerInfo.name; */
1522     ServerInfo.description = NULL;
1523     DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1524     DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1525    
1526     memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1527     ServerInfo.specific_ipv4_vhost = 0;
1528     memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
1529     ServerInfo.specific_ipv6_vhost = 0;
1530    
1531     ServerInfo.max_clients = MAXCLIENTS_MAX;
1532     /* Don't reset hub, as that will break lazylinks */
1533     /* ServerInfo.hub = NO; */
1534     ServerInfo.dns_host.sin_addr.s_addr = 0;
1535     ServerInfo.dns_host.sin_port = 0;
1536     AdminInfo.name = NULL;
1537     AdminInfo.email = NULL;
1538     AdminInfo.description = NULL;
1539    
1540     set_log_level(L_NOTICE);
1541     ConfigLoggingEntry.use_logging = 1;
1542     ConfigLoggingEntry.operlog[0] = '\0';
1543     ConfigLoggingEntry.userlog[0] = '\0';
1544     ConfigLoggingEntry.klinelog[0] = '\0';
1545     ConfigLoggingEntry.glinelog[0] = '\0';
1546     ConfigLoggingEntry.killlog[0] = '\0';
1547     ConfigLoggingEntry.operspylog[0] = '\0';
1548     ConfigLoggingEntry.ioerrlog[0] = '\0';
1549     ConfigLoggingEntry.failed_operlog[0] = '\0';
1550    
1551     ConfigChannel.restrict_channels = NO;
1552     ConfigChannel.disable_local_channels = NO;
1553     ConfigChannel.use_invex = YES;
1554     ConfigChannel.use_except = YES;
1555     ConfigChannel.use_knock = YES;
1556     ConfigChannel.knock_delay = 300;
1557     ConfigChannel.knock_delay_channel = 60;
1558     ConfigChannel.invite_ops_only = YES;
1559     ConfigChannel.max_chans_per_user = 15;
1560     ConfigChannel.quiet_on_ban = YES;
1561     ConfigChannel.max_bans = 25;
1562     ConfigChannel.default_split_user_count = 0;
1563     ConfigChannel.default_split_server_count = 0;
1564     ConfigChannel.no_join_on_split = NO;
1565     ConfigChannel.no_create_on_split = NO;
1566     ConfigChannel.burst_topicwho = YES;
1567    
1568     ConfigServerHide.flatten_links = NO;
1569     ConfigServerHide.links_delay = 300;
1570     ConfigServerHide.hidden = NO;
1571     ConfigServerHide.disable_hidden = NO;
1572     ConfigServerHide.hide_servers = NO;
1573     DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1574     ConfigServerHide.hide_server_ips = NO;
1575    
1576     ConfigFileEntry.gline_min_cidr = 16;
1577     ConfigFileEntry.gline_min_cidr6 = 48;
1578     ConfigFileEntry.invisible_on_connect = YES;
1579     ConfigFileEntry.burst_away = NO;
1580     ConfigFileEntry.use_whois_actually = YES;
1581     ConfigFileEntry.tkline_expire_notices = YES;
1582     ConfigFileEntry.hide_spoof_ips = YES;
1583     ConfigFileEntry.ignore_bogus_ts = NO;
1584     ConfigFileEntry.disable_auth = NO;
1585     ConfigFileEntry.disable_remote = NO;
1586     ConfigFileEntry.kill_chase_time_limit = 90;
1587     ConfigFileEntry.default_floodcount = 8; /* XXX */
1588     ConfigFileEntry.failed_oper_notice = YES;
1589     ConfigFileEntry.dots_in_ident = 0; /* XXX */
1590     ConfigFileEntry.dot_in_ip6_addr = YES;
1591     ConfigFileEntry.min_nonwildcard = 4;
1592     ConfigFileEntry.min_nonwildcard_simple = 3;
1593     ConfigFileEntry.max_accept = 20;
1594     ConfigFileEntry.anti_nick_flood = NO; /* XXX */
1595     ConfigFileEntry.max_nick_time = 20;
1596     ConfigFileEntry.max_nick_changes = 5;
1597     ConfigFileEntry.anti_spam_exit_message_time = 0; /* XXX */
1598     ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1599     ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT; /* XXX */
1600     ConfigFileEntry.kline_with_reason = YES;
1601     ConfigFileEntry.kline_reason = NULL;
1602     ConfigFileEntry.warn_no_nline = YES;
1603     ConfigFileEntry.stats_o_oper_only = NO; /* XXX */
1604     ConfigFileEntry.stats_k_oper_only = 1; /* masked */
1605     ConfigFileEntry.stats_i_oper_only = 1; /* masked */
1606     ConfigFileEntry.stats_P_oper_only = NO;
1607     ConfigFileEntry.caller_id_wait = 60;
1608     ConfigFileEntry.opers_bypass_callerid = NO;
1609     ConfigFileEntry.pace_wait = 10;
1610     ConfigFileEntry.pace_wait_simple = 1;
1611     ConfigFileEntry.short_motd = NO;
1612     ConfigFileEntry.ping_cookie = NO;
1613     ConfigFileEntry.no_oper_flood = NO; /* XXX */
1614     ConfigFileEntry.true_no_oper_flood = NO; /* XXX */
1615     ConfigFileEntry.oper_pass_resv = YES;
1616     ConfigFileEntry.glines = NO; /* XXX */
1617     ConfigFileEntry.gline_time = 12 * 3600; /* XXX */
1618     ConfigFileEntry.idletime = 0;
1619     ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1620     ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1621     ConfigFileEntry.oper_only_umodes = UMODE_DEBUG; /* XXX */
1622     ConfigFileEntry.oper_umodes = UMODE_LOCOPS | UMODE_SERVNOTICE |
1623     UMODE_OPERWALL | UMODE_WALLOP; /* XXX */
1624     DupString(ConfigFileEntry.servlink_path, SLPATH);
1625     #ifdef HAVE_LIBCRYPTO
1626     /* jdc -- This is our default value for a cipher. According to the
1627     * CRYPTLINK document (doc/cryptlink.txt), BF/128 must be supported
1628     * under all circumstances if cryptlinks are enabled. So,
1629     * this will be our default.
1630     *
1631     * NOTE: I apologise for the hard-coded value of "1" (BF/128).
1632     * This should be moved into a find_cipher() routine.
1633     */
1634     ConfigFileEntry.default_cipher_preference = &CipherTable[1];
1635     #endif
1636     ConfigFileEntry.use_egd = NO;
1637     ConfigFileEntry.egdpool_path = NULL;
1638     #ifdef HAVE_LIBZ
1639     ConfigFileEntry.compression_level = 0;
1640     #endif
1641     ConfigFileEntry.throttle_time = 10;
1642     }
1643    
1644     /* read_conf()
1645     *
1646     * inputs - file descriptor pointing to config file to use
1647     * output - None
1648     * side effects - Read configuration file.
1649     */
1650     static void
1651     read_conf(FBFILE *file)
1652     {
1653     scount = lineno = 0;
1654    
1655     set_default_conf(); /* Set default values prior to conf parsing */
1656     ypass = 1;
1657     yyparse(); /* pick up the classes first */
1658    
1659     fbrewind(file);
1660    
1661     ypass = 2;
1662     yyparse(); /* Load the values from the conf */
1663     validate_conf(); /* Check to make sure some values are still okay. */
1664     /* Some global values are also loaded here. */
1665     check_class(); /* Make sure classes are valid */
1666     }
1667    
1668     static void
1669     validate_conf(void)
1670     {
1671     if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1672     ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1673    
1674     if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1675     ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1676    
1677     if (ConfigFileEntry.servlink_path == NULL)
1678     DupString(ConfigFileEntry.servlink_path, SLPATH);
1679    
1680     if (ServerInfo.network_name == NULL)
1681     DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1682    
1683     if (ServerInfo.network_desc == NULL)
1684     DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1685    
1686     if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1687     (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1688     ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1689     }
1690    
1691     /* lookup_confhost()
1692     *
1693 db 130 * inputs - pointer to ConfItem
1694     * output - NONE
1695     * side effects - start DNS lookups of all hostnames in the conf
1696 adx 30 * line and convert an IP addresses in a.b.c.d number for to IP#s.
1697     */
1698     static void
1699     lookup_confhost(struct ConfItem *conf)
1700     {
1701     struct AccessItem *aconf;
1702     struct addrinfo hints, *res;
1703    
1704 db 139 aconf = &conf->conf.AccessItem;
1705 adx 30
1706     if (EmptyString(aconf->host) ||
1707     EmptyString(aconf->user))
1708     {
1709     ilog(L_ERROR, "Host/server name error: (%s) (%s)",
1710     aconf->host, conf->name);
1711     return;
1712     }
1713    
1714     if (strchr(aconf->host, '*') ||
1715     strchr(aconf->host, '?'))
1716     return;
1717    
1718     /* Do name lookup now on hostnames given and store the
1719     * ip numbers in conf structure.
1720     */
1721     memset(&hints, 0, sizeof(hints));
1722    
1723     hints.ai_family = AF_UNSPEC;
1724     hints.ai_socktype = SOCK_STREAM;
1725    
1726     /* Get us ready for a bind() and don't bother doing dns lookup */
1727     hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1728    
1729     if (irc_getaddrinfo(aconf->host, NULL, &hints, &res))
1730     {
1731     conf_dns_lookup(aconf);
1732     return;
1733     }
1734    
1735     assert(res != NULL);
1736    
1737     memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
1738     aconf->ipnum.ss_len = res->ai_addrlen;
1739     aconf->ipnum.ss.ss_family = res->ai_family;
1740     irc_freeaddrinfo(res);
1741     }
1742    
1743     /* conf_connect_allowed()
1744     *
1745     * inputs - pointer to inaddr
1746     * - int type ipv4 or ipv6
1747     * output - BANNED or accepted
1748     * side effects - none
1749     */
1750     int
1751     conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1752     {
1753     struct ip_entry *ip_found;
1754     struct AccessItem *aconf = find_dline_conf(addr, aftype);
1755    
1756     /* DLINE exempt also gets you out of static limits/pacing... */
1757     if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1758     return 0;
1759    
1760     if (aconf != NULL)
1761     return BANNED_CLIENT;
1762    
1763     ip_found = find_or_add_ip(addr);
1764 michael 129 ip_found->last_attempt = CurrentTime;
1765 adx 30
1766     if ((CurrentTime - ip_found->last_attempt) <
1767     ConfigFileEntry.throttle_time)
1768     return TOO_FAST;
1769    
1770     return 0;
1771     }
1772    
1773     /* oper_privs_as_string()
1774     *
1775 michael 57 * inputs - pointer to client_p
1776 adx 30 * output - pointer to static string showing oper privs
1777     * side effects - return as string, the oper privs as derived from port
1778     */
1779 michael 57 static const struct oper_privs
1780     {
1781     const unsigned int oprivs;
1782     const unsigned int hidden;
1783     const unsigned char c;
1784     } flag_list[] = {
1785     { OPER_FLAG_ADMIN, OPER_FLAG_HIDDEN_ADMIN, 'A' },
1786     { OPER_FLAG_REMOTEBAN, 0, 'B' },
1787     { OPER_FLAG_DIE, 0, 'D' },
1788     { OPER_FLAG_GLINE, 0, 'G' },
1789     { OPER_FLAG_REHASH, 0, 'H' },
1790     { OPER_FLAG_K, 0, 'K' },
1791     { OPER_FLAG_OPERWALL, 0, 'L' },
1792     { OPER_FLAG_N, 0, 'N' },
1793     { OPER_FLAG_GLOBAL_KILL, 0, 'O' },
1794     { OPER_FLAG_REMOTE, 0, 'R' },
1795     { OPER_FLAG_OPER_SPY, 0, 'S' },
1796     { OPER_FLAG_UNKLINE, 0, 'U' },
1797     { OPER_FLAG_X, 0, 'X' },
1798     { 0, 0, '\0' }
1799     };
1800 adx 30
1801     char *
1802     oper_privs_as_string(const unsigned int port)
1803     {
1804 michael 57 static char privs_out[16];
1805     char *privs_ptr = privs_out;
1806     unsigned int i = 0;
1807 adx 30
1808 michael 57 for (; flag_list[i].oprivs; ++i)
1809     {
1810     if ((port & flag_list[i].oprivs) &&
1811     (port & flag_list[i].hidden) == 0)
1812     *privs_ptr++ = flag_list[i].c;
1813     else
1814     *privs_ptr++ = ToLowerTab[flag_list[i].c];
1815     }
1816    
1817     *privs_ptr = '\0';
1818    
1819 adx 30 return privs_out;
1820     }
1821    
1822     /*
1823     * Input: A client to find the active oper{} name for.
1824     * Output: The nick!user@host{oper} of the oper.
1825     * "oper" is server name for remote opers
1826     * Side effects: None.
1827     */
1828     char *
1829     get_oper_name(const struct Client *client_p)
1830     {
1831     /* +5 for !,@,{,} and null */
1832     static char buffer[NICKLEN+USERLEN+HOSTLEN+HOSTLEN+5];
1833    
1834 db 130 if (MyConnect(client_p) && IsOper(client_p))
1835 db 101 ircsprintf(buffer, "%s!%s@%s{%s}", client_p->name,
1836     client_p->username, client_p->host,
1837 michael 129 client_p->localClient->auth_oper);
1838 db 128 else
1839     ircsprintf(buffer, "%s!%s@%s{%s}", client_p->name,
1840 michael 129 client_p->username, client_p->host,
1841     client_p->servptr->name);
1842 adx 30 return buffer;
1843     }
1844    
1845     /* read_conf_files()
1846     *
1847     * inputs - cold start YES or NO
1848     * output - none
1849     * side effects - read all conf files needed, ircd.conf kline.conf etc.
1850     */
1851     void
1852     read_conf_files(int cold)
1853     {
1854     const char *filename;
1855     char chanmodes[32];
1856     char chanlimit[32];
1857    
1858     filename = get_conf_name(CONF_TYPE);
1859    
1860     /* We need to know the initial filename for the yyerror() to report
1861     FIXME: The full path is in conffilenamebuf first time since we
1862     dont know anything else
1863    
1864     - Gozem 2002-07-21
1865     */
1866     strlcpy(conffilebuf, filename, sizeof(conffilebuf));
1867    
1868     if ((conf_fbfile_in = fbopen(filename, "r")) == NULL)
1869     {
1870     if (cold)
1871     {
1872     ilog(L_CRIT, "Unable to read configuration file '%s': %s",
1873     filename, strerror(errno));
1874     exit(-1);
1875     }
1876     else
1877     {
1878     sendto_realops_flags(UMODE_ALL, L_ALL,
1879     "Unable to read configuration file '%s': %s",
1880     filename, strerror(errno));
1881     return;
1882     }
1883     }
1884    
1885     if (!cold)
1886     clear_out_old_conf();
1887    
1888     read_conf(conf_fbfile_in);
1889     fbclose(conf_fbfile_in);
1890    
1891     add_isupport("NETWORK", ServerInfo.network_name, -1);
1892     ircsprintf(chanmodes, "b%s%s:%d", ConfigChannel.use_except ? "e" : "",
1893     ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
1894     add_isupport("MAXLIST", chanmodes, -1);
1895     add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1896     if (ConfigChannel.disable_local_channels)
1897     add_isupport("CHANTYPES", "#", -1);
1898     else
1899     add_isupport("CHANTYPES", "#&", -1);
1900     ircsprintf(chanlimit, "%s:%d", ConfigChannel.disable_local_channels ? "#" : "#&",
1901     ConfigChannel.max_chans_per_user);
1902     add_isupport("CHANLIMIT", chanlimit, -1);
1903     ircsprintf(chanmodes, "%s%s%s", ConfigChannel.use_except ? "e" : "",
1904     ConfigChannel.use_invex ? "I" : "", "b,k,l,imnpst");
1905 michael 99 add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
1906 adx 30 if (ConfigChannel.use_except)
1907     add_isupport("EXCEPTS", "e", -1);
1908     if (ConfigChannel.use_invex)
1909     add_isupport("INVEX", "I", -1);
1910     add_isupport("CHANMODES", chanmodes, -1);
1911    
1912     /*
1913     * message_locale may have changed. rebuild isupport since it relies
1914     * on strlen(form_str(RPL_ISUPPORT))
1915     */
1916     rebuild_isupport_message_line();
1917    
1918     parse_conf_file(KLINE_TYPE, cold);
1919     parse_conf_file(RKLINE_TYPE, cold);
1920     parse_conf_file(DLINE_TYPE, cold);
1921     parse_conf_file(XLINE_TYPE, cold);
1922     parse_conf_file(RXLINE_TYPE, cold);
1923     parse_conf_file(NRESV_TYPE, cold);
1924     parse_conf_file(CRESV_TYPE, cold);
1925     }
1926    
1927     /* parse_conf_file()
1928     *
1929     * inputs - type of conf file to parse
1930     * output - none
1931     * side effects - conf file for givenconf type is opened and read then parsed
1932     */
1933     static void
1934     parse_conf_file(int type, int cold)
1935     {
1936     FBFILE *file = NULL;
1937     const char *filename = get_conf_name(type);
1938    
1939     if ((file = fbopen(filename, "r")) == NULL)
1940     {
1941     if (cold)
1942     ilog(L_ERROR, "Unable to read configuration file '%s': %s",
1943     filename, strerror(errno));
1944     else
1945     sendto_realops_flags(UMODE_ALL, L_ALL,
1946     "Unable to read configuration file '%s': %s",
1947     filename, strerror(errno));
1948     }
1949     else
1950     {
1951     parse_csv_file(file, type);
1952     fbclose(file);
1953     }
1954     }
1955    
1956     /* clear_out_old_conf()
1957     *
1958     * inputs - none
1959     * output - none
1960     * side effects - Clear out the old configuration
1961     */
1962     static void
1963     clear_out_old_conf(void)
1964     {
1965     dlink_node *ptr = NULL, *next_ptr = NULL;
1966     struct ConfItem *conf;
1967     struct AccessItem *aconf;
1968     struct ClassItem *cltmp;
1969     struct MatchItem *match_item;
1970     dlink_list *free_items [] = {
1971 michael 129 &server_items, &oconf_items, &hub_items, &leaf_items,
1972 adx 30 &uconf_items, &xconf_items, &rxconf_items, &rkconf_items,
1973     &nresv_items, &cluster_items, &gdeny_items, NULL
1974     };
1975    
1976     dlink_list ** iterator = free_items; /* C is dumb */
1977    
1978     /* We only need to free anything allocated by yyparse() here.
1979     * Resetting structs, etc, is taken care of by set_default_conf().
1980     */
1981    
1982     for (; *iterator != NULL; iterator++)
1983     {
1984     DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1985     {
1986     conf = ptr->data;
1987     /* XXX This is less than pretty */
1988     if (conf->type == SERVER_TYPE)
1989     {
1990 db 139 aconf = &conf->conf.AccessItem;
1991 adx 30 if (aconf->clients != 0)
1992     {
1993     SetConfIllegal(aconf);
1994     dlinkDelete(&conf->node, &server_items);
1995     }
1996     else
1997     {
1998     delete_conf_item(conf);
1999     }
2000     }
2001     else if (conf->type == OPER_TYPE)
2002     {
2003 db 139 aconf = &conf->conf.AccessItem;
2004 adx 30 if (aconf->clients != 0)
2005     {
2006     SetConfIllegal(aconf);
2007     dlinkDelete(&conf->node, &oconf_items);
2008     }
2009     else
2010     {
2011     delete_conf_item(conf);
2012     }
2013     }
2014     else if (conf->type == CLIENT_TYPE)
2015     {
2016 db 139 aconf = &conf->conf.AccessItem;
2017 adx 30 if (aconf->clients != 0)
2018     {
2019     SetConfIllegal(aconf);
2020     }
2021     else
2022     {
2023     delete_conf_item(conf);
2024     }
2025     }
2026     else if (conf->type == XLINE_TYPE ||
2027     conf->type == RXLINE_TYPE ||
2028     conf->type == RKLINE_TYPE)
2029     {
2030     /* temporary (r)xlines are also on
2031     * the (r)xconf items list */
2032     if (conf->flags & CONF_FLAGS_TEMPORARY)
2033     continue;
2034    
2035     delete_conf_item(conf);
2036     }
2037     else
2038     {
2039     if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2040     {
2041 db 139 match_item = &conf->conf.MatchItem;
2042 adx 30 if ((match_item->ref_count <= 0))
2043     delete_conf_item(conf);
2044     else
2045     {
2046     match_item->illegal = 1;
2047     dlinkDelete(&conf->node, *iterator);
2048     }
2049     }
2050     else
2051     delete_conf_item(conf);
2052     }
2053     }
2054     }
2055    
2056     /* don't delete the class table, rather mark all entries
2057     * for deletion. The table is cleaned up by check_class. - avalon
2058     */
2059     DLINK_FOREACH(ptr, class_items.head)
2060     {
2061     conf = ptr->data;
2062 db 139 cltmp = &conf->conf.ClassItem;
2063 adx 30 if (ptr != class_items.tail) /* never mark the "default" class */
2064     MaxTotal(cltmp) = -1;
2065     }
2066    
2067     clear_out_address_conf();
2068    
2069     /* clean out module paths */
2070     #ifndef STATIC_MODULES
2071     mod_clear_paths();
2072     #endif
2073    
2074     /* clean out ServerInfo */
2075     MyFree(ServerInfo.description);
2076     ServerInfo.description = NULL;
2077     MyFree(ServerInfo.network_name);
2078     ServerInfo.network_name = NULL;
2079     MyFree(ServerInfo.network_desc);
2080     ServerInfo.network_desc = NULL;
2081     MyFree(ConfigFileEntry.egdpool_path);
2082     ConfigFileEntry.egdpool_path = NULL;
2083     #ifdef HAVE_LIBCRYPTO
2084     if (ServerInfo.rsa_private_key != NULL)
2085     {
2086     RSA_free(ServerInfo.rsa_private_key);
2087     ServerInfo.rsa_private_key = NULL;
2088     }
2089    
2090     MyFree(ServerInfo.rsa_private_key_file);
2091     ServerInfo.rsa_private_key_file = NULL;
2092     #endif
2093    
2094     /* clean out old resvs from the conf */
2095     clear_conf_resv();
2096    
2097     /* clean out AdminInfo */
2098     MyFree(AdminInfo.name);
2099     AdminInfo.name = NULL;
2100     MyFree(AdminInfo.email);
2101     AdminInfo.email = NULL;
2102     MyFree(AdminInfo.description);
2103     AdminInfo.description = NULL;
2104    
2105     /* operator{} and class{} blocks are freed above */
2106     /* clean out listeners */
2107     close_listeners();
2108    
2109     /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2110     * exempt{} and gecos{} blocks are freed above too
2111     */
2112    
2113     /* clean out general */
2114     MyFree(ConfigFileEntry.servlink_path);
2115     ConfigFileEntry.servlink_path = NULL;
2116     #ifdef HAVE_LIBCRYPTO
2117     ConfigFileEntry.default_cipher_preference = NULL;
2118     #endif /* HAVE_LIBCRYPTO */
2119     delete_isupport("INVEX");
2120     delete_isupport("EXCEPTS");
2121     }
2122    
2123     /* flush_deleted_I_P()
2124     *
2125     * inputs - none
2126     * output - none
2127     * side effects - This function removes I/P conf items
2128     */
2129     static void
2130     flush_deleted_I_P(void)
2131     {
2132     dlink_node *ptr;
2133     dlink_node *next_ptr;
2134     struct ConfItem *conf;
2135     struct AccessItem *aconf;
2136     dlink_list * free_items [] = {
2137     &server_items, &oconf_items, &hub_items, &leaf_items, NULL
2138     };
2139     dlink_list ** iterator = free_items; /* C is dumb */
2140    
2141     /* flush out deleted I and P lines
2142     * although still in use.
2143     */
2144     for (; *iterator != NULL; iterator++)
2145     {
2146     DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2147     {
2148     conf = ptr->data;
2149 db 139 aconf = &conf->conf.AccessItem;
2150 adx 30
2151     if (IsConfIllegal(aconf))
2152     {
2153     dlinkDelete(ptr, *iterator);
2154    
2155     if (aconf->clients == 0)
2156     delete_conf_item(conf);
2157     }
2158     }
2159     }
2160     }
2161    
2162     /* get_conf_name()
2163     *
2164     * inputs - type of conf file to return name of file for
2165     * output - pointer to filename for type of conf
2166     * side effects - none
2167     */
2168     const char *
2169     get_conf_name(ConfType type)
2170     {
2171     switch (type)
2172     {
2173     case CONF_TYPE:
2174     return ConfigFileEntry.configfile;
2175     break;
2176     case KLINE_TYPE:
2177     return ConfigFileEntry.klinefile;
2178     break;
2179     case RKLINE_TYPE:
2180     return ConfigFileEntry.rklinefile;
2181     break;
2182     case DLINE_TYPE:
2183     return ConfigFileEntry.dlinefile;
2184     break;
2185     case XLINE_TYPE:
2186     return ConfigFileEntry.xlinefile;
2187     break;
2188     case RXLINE_TYPE:
2189     return ConfigFileEntry.rxlinefile;
2190     break;
2191     case CRESV_TYPE:
2192     return ConfigFileEntry.cresvfile;
2193     break;
2194     case NRESV_TYPE:
2195     return ConfigFileEntry.nresvfile;
2196     break;
2197     case GLINE_TYPE:
2198     return ConfigFileEntry.glinefile;
2199     break;
2200    
2201     default:
2202     return NULL; /* This should NEVER HAPPEN since we call this function
2203     only with the above values, this will cause us to core
2204     at some point if this happens so we know where it was */
2205     }
2206     }
2207    
2208    
2209 db 128 /* get_client_className()
2210 adx 30 *
2211     * inputs - pointer to client struct
2212     * output - pointer to name of class
2213     * side effects - NONE
2214     */
2215     const char *
2216 db 128 get_client_className(struct Client *target_p)
2217 adx 30 {
2218 db 130 assert(target_p && !IsMe(target_p));
2219 adx 30
2220 michael 129 if (target_p->localClient->class != NULL)
2221 adx 30 {
2222 db 139 struct ConfItem *conf = target_p->localClient->class->conf;
2223 db 128 return conf->name;
2224 adx 30 }
2225    
2226     return "default";
2227     }
2228    
2229 db 126 #define BAD_PING (-1)
2230 adx 30 /* get_client_ping()
2231     *
2232     * inputs - pointer to client struct
2233     * - pointer to a variable that receives ping warning time
2234     * output - ping frequency
2235     * side effects - NONE
2236     */
2237     int
2238     get_client_ping(struct Client *target_p, int *pingwarn)
2239     {
2240 db 126 struct ClassItem *aclass;
2241 adx 30 int ping;
2242    
2243 db 126 if (target_p->localClient->class != NULL)
2244 db 101 {
2245 db 126 aclass = target_p->localClient->class;
2246     ping = PingFreq(aclass);
2247     *pingwarn = PingWarning(aclass);
2248 db 101 if (ping > 0)
2249     return ping;
2250     }
2251 db 126 else
2252     {
2253     *pingwarn = 0;
2254     return BAD_PING;
2255     }
2256 adx 30
2257     *pingwarn = 0;
2258     return DEFAULT_PINGFREQUENCY;
2259     }
2260    
2261     /* find_class()
2262     *
2263     * inputs - string name of class
2264     * output - corresponding Class pointer
2265     * side effects - NONE
2266     */
2267     struct ConfItem *
2268     find_class(const char *classname)
2269     {
2270     struct ConfItem *conf;
2271    
2272     if ((conf = find_exact_name_conf(CLASS_TYPE, classname, NULL, NULL)) != NULL)
2273     return(conf);
2274    
2275     return class_default;
2276     }
2277    
2278     /* check_class()
2279     *
2280     * inputs - NONE
2281     * output - NONE
2282     * side effects -
2283     */
2284     void
2285     check_class(void)
2286     {
2287     dlink_node *ptr;
2288     dlink_node *next_ptr;
2289     struct ConfItem *conf;
2290     struct ClassItem *aclass;
2291    
2292     DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2293     {
2294     conf = ptr->data;
2295 db 139 aclass = &conf->conf.ClassItem;
2296 adx 30
2297     if (MaxTotal(aclass) < 0)
2298     {
2299     destroy_cidr_class(aclass);
2300     if (CurrUserCount(aclass) > 0)
2301     dlinkDelete(&conf->node, &class_items);
2302     else
2303     delete_conf_item(conf);
2304     }
2305     }
2306     }
2307    
2308     /* init_class()
2309     *
2310     * inputs - NONE
2311     * output - NONE
2312     * side effects -
2313     */
2314     void
2315     init_class(void)
2316     {
2317     struct ClassItem *aclass;
2318    
2319     class_default = make_conf_item(CLASS_TYPE);
2320 db 139 aclass = &class_default->conf.ClassItem;
2321 adx 30 DupString(class_default->name, "default");
2322     ConFreq(aclass) = DEFAULT_CONNECTFREQUENCY;
2323     PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
2324     MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
2325     MaxSendq(aclass) = DEFAULT_SENDQ;
2326 db 128 CurrUserCount(aclass) = 0;
2327 adx 30
2328     client_check_cb = register_callback("check_client", check_client);
2329     }
2330    
2331     /* get_sendq()
2332     *
2333     * inputs - pointer to client
2334     * output - sendq for this client as found from its class
2335     * side effects - NONE
2336     */
2337     unsigned long
2338     get_sendq(struct Client *client_p)
2339     {
2340     unsigned long sendq = DEFAULT_SENDQ;
2341     struct ClassItem *aclass;
2342    
2343 db 126 if (client_p && !IsMe(client_p) && (client_p->localClient->class))
2344 adx 30 {
2345 db 126 aclass = client_p->localClient->class;
2346     sendq = MaxSendq(aclass);
2347 adx 30 }
2348 db 101 return sendq;
2349 adx 30 }
2350    
2351     /* conf_add_class_to_conf()
2352     *
2353     * inputs - pointer to config item
2354     * output - NONE
2355     * side effects - Add a class pointer to a conf
2356     */
2357     void
2358     conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
2359     {
2360     struct AccessItem *aconf;
2361     struct ClassItem *aclass;
2362    
2363 db 139 aconf = &conf->conf.AccessItem;
2364 adx 30
2365     if (class_name == NULL)
2366     {
2367     aconf->class_ptr = class_default;
2368     if (conf->type == CLIENT_TYPE)
2369     sendto_realops_flags(UMODE_ALL, L_ALL,
2370     "Warning *** Defaulting to default class for %s@%s",
2371     aconf->user, aconf->host);
2372     else
2373     sendto_realops_flags(UMODE_ALL, L_ALL,
2374     "Warning *** Defaulting to default class for %s",
2375     conf->name);
2376     }
2377     else
2378     {
2379     aconf->class_ptr = find_class(class_name);
2380     }
2381    
2382     if (aconf->class_ptr == NULL)
2383     {
2384     if (conf->type == CLIENT_TYPE)
2385     sendto_realops_flags(UMODE_ALL, L_ALL,
2386     "Warning *** Defaulting to default class for %s@%s",
2387     aconf->user, aconf->host);
2388     else
2389     sendto_realops_flags(UMODE_ALL, L_ALL,
2390     "Warning *** Defaulting to default class for %s",
2391     conf->name);
2392     aconf->class_ptr = class_default;
2393     }
2394     else
2395     {
2396 db 139 aclass = &conf->conf.ClassItem;
2397 adx 30 if (MaxTotal(aclass) < 0)
2398     {
2399     aconf->class_ptr = class_default;
2400     }
2401     }
2402     }
2403    
2404     #define MAXCONFLINKS 150
2405    
2406     /* conf_add_server()
2407     *
2408     * inputs - pointer to config item
2409     * - pointer to link count already on this conf
2410     * output - NONE
2411     * side effects - Add a connect block
2412     */
2413     int
2414     conf_add_server(struct ConfItem *conf, unsigned int lcount, const char *class_name)
2415     {
2416     struct AccessItem *aconf;
2417     char *orig_host;
2418    
2419 db 139 aconf = &conf->conf.AccessItem;
2420 adx 30
2421     conf_add_class_to_conf(conf, class_name);
2422    
2423     if (lcount > MAXCONFLINKS || !aconf->host || !conf->name)
2424     {
2425     sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
2426     ilog(L_WARN, "Bad connect block");
2427     return -1;
2428     }
2429    
2430     if (EmptyString(aconf->passwd) && !IsConfCryptLink(aconf))
2431     {
2432     sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
2433     conf->name);
2434     ilog(L_WARN, "Bad connect block, host %s", conf->name);
2435     return -1;
2436     }
2437    
2438     orig_host = aconf->host;
2439     split_nuh(orig_host, NULL, &aconf->user, &aconf->host);
2440     MyFree(orig_host);
2441     lookup_confhost(conf);
2442    
2443     return 0;
2444     }
2445    
2446     /* conf_add_d_conf()
2447     *
2448     * inputs - pointer to config item
2449     * output - NONE
2450     * side effects - Add a d/D line
2451     */
2452     void
2453     conf_add_d_conf(struct AccessItem *aconf)
2454     {
2455     if (aconf->host == NULL)
2456     return;
2457    
2458     aconf->user = NULL;
2459    
2460     /* XXX - Should 'd' ever be in the old conf? For new conf we don't
2461     * need this anyway, so I will disable it for now... -A1kmm
2462     */
2463     if (parse_netmask(aconf->host, NULL, NULL) == HM_HOST)
2464     {
2465     ilog(L_WARN, "Invalid Dline %s ignored", aconf->host);
2466 db 140 delete_conf_item(aconf->conf);
2467 adx 30 }
2468     else
2469     {
2470     /* XXX ensure user is NULL */
2471     MyFree(aconf->user);
2472     aconf->user = NULL;
2473     add_conf_by_address(CONF_DLINE, aconf);
2474     }
2475     }
2476    
2477     /* yyerror()
2478     *
2479     * inputs - message from parser
2480     * output - NONE
2481     * side effects - message to opers and log file entry is made
2482     */
2483     void
2484     yyerror(const char *msg)
2485     {
2486     char newlinebuf[IRCD_BUFSIZE];
2487    
2488     if (ypass != 1)
2489     return;
2490    
2491     strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
2492     sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
2493     conffilebuf, lineno + 1, msg, newlinebuf);
2494     ilog(L_WARN, "\"%s\", line %u: %s: %s",
2495     conffilebuf, lineno + 1, msg, newlinebuf);
2496     }
2497    
2498     int
2499     conf_fbgets(char *lbuf, unsigned int max_size, FBFILE *fb)
2500     {
2501     if (fbgets(lbuf, max_size, fb) == NULL)
2502     return 0;
2503    
2504     return strlen(lbuf);
2505     }
2506    
2507     int
2508     conf_yy_fatal_error(const char *msg)
2509     {
2510     return 0;
2511     }
2512    
2513     /* match_conf_password()
2514     *
2515     * inputs - pointer to given password
2516     * - pointer to Conf
2517     * output - 1 or 0 if match
2518     * side effects - none
2519     */
2520     int
2521     match_conf_password(const char *password, const struct AccessItem *aconf)
2522     {
2523     const char *encr = NULL;
2524    
2525     if (password == NULL || aconf->passwd == NULL)
2526     return 0;
2527    
2528     if (aconf->flags & CONF_FLAGS_ENCRYPTED)
2529     {
2530     /* use first two chars of the password they send in as salt */
2531     /* If the password in the conf is MD5, and ircd is linked
2532     * to scrypt on FreeBSD, or the standard crypt library on
2533     * glibc Linux, then this code will work fine on generating
2534     * the proper encrypted hash for comparison.
2535     */
2536     if (*aconf->passwd)
2537     encr = crypt(password, aconf->passwd);
2538     else
2539     encr = "";
2540     }
2541     else
2542     encr = password;
2543    
2544     return !strcmp(encr, aconf->passwd);
2545     }
2546    
2547    
2548     /*
2549     * split_nuh
2550     *
2551     * inputs - pointer to original mask (modified in place)
2552     * - pointer to pointer where nick should go
2553     * - pointer to pointer where user should go
2554     * - pointer to pointer where host should go
2555     * output - NONE
2556     * side effects - mask is modified in place
2557     * If nick pointer is NULL, ignore writing to it
2558     * this allows us to use this function elsewhere.
2559     *
2560     * mask nick user host
2561     * ---------------------- ------- ------- ------
2562     * Dianora!db@db.net Dianora db db.net
2563     * Dianora Dianora * *
2564     * db.net * * db.net
2565     * OR if nick pointer is NULL
2566     * Dianora - * Dianora
2567     * Dianora! Dianora * *
2568     * Dianora!@ Dianora * *
2569     * Dianora!db Dianora db *
2570     * Dianora!@db.net Dianora * db.net
2571     * db@db.net * db db.net
2572     * !@ * * *
2573     * @ * * *
2574     * ! * * *
2575     */
2576    
2577     void
2578     split_nuh(char *mask, char **nick, char **user, char **host)
2579     {
2580     char *p = NULL, *q = NULL;
2581    
2582     if ((p = strchr(mask, '!')) != NULL)
2583     {
2584     *p = '\0';
2585     if (nick != NULL)
2586     {
2587     if (*mask != '\0')
2588     *nick = xstrldup(mask, NICKLEN);
2589     else
2590     DupString(*nick, "*");
2591     }
2592    
2593     if ((q = strchr(++p, '@')) != NULL)
2594     {
2595     *q = '\0';
2596    
2597     if (*p != '\0')
2598     *user = xstrldup(p, USERLEN+1);
2599     else
2600     DupString(*user, "*");
2601    
2602     if (*++q != '\0')
2603     *host = xstrldup(q, HOSTLEN+1);
2604     else
2605     DupString(*host, "*");
2606     }
2607     else
2608     {
2609     if (*p != '\0')
2610     *user = xstrldup(p, USERLEN+1);
2611     else
2612     DupString(*user, "*");
2613    
2614     DupString(*host, "*");
2615     }
2616     }
2617     else /* No ! found so lets look for a user@host */
2618     {
2619     if ((p = strchr(mask, '@')) != NULL) /* if found a @ */
2620     {
2621     if (nick != NULL)
2622     DupString(*nick, "*");
2623     *p = '\0';
2624    
2625     if (*mask != '\0')
2626     *user = xstrldup(mask, USERLEN+1);
2627     else
2628     DupString(*user, "*");
2629    
2630     if (*++p != '\0')
2631     *host = xstrldup(p, HOSTLEN+1);
2632     else
2633     DupString(*host, "*");
2634     }
2635     else /* no @ found */
2636     {
2637     if (nick != NULL)
2638     {
2639     if (strpbrk(mask, ".:"))
2640     {
2641     DupString(*nick, "*");
2642     *host = xstrldup(mask, HOSTLEN+1);
2643     }
2644     else
2645     {
2646     *nick = xstrldup(mask, NICKLEN);
2647     DupString(*host, "*");
2648     }
2649    
2650     DupString(*user, "*");
2651     }
2652     else
2653     {
2654     DupString(*user, "*");
2655     *host = xstrldup(mask, HOSTLEN+1);
2656     }
2657     }
2658     }
2659     }
2660    
2661     /*
2662     * flags_to_ascii
2663     *
2664     * inputs - flags is a bitmask
2665     * - pointer to table of ascii letters corresponding
2666     * to each bit
2667     * - flag 1 for convert ToLower if bit missing
2668     * 0 if ignore.
2669     * output - none
2670     * side effects - string pointed to by p has bitmap chars written to it
2671     */
2672     static void
2673     flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
2674     int lowerit)
2675     {
2676     unsigned int mask = 1;
2677     int i = 0;
2678    
2679     for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
2680     {
2681     if (flags & mask)
2682     *p++ = bit_table[i];
2683     else if(lowerit)
2684     *p++ = ToLower(bit_table[i]);
2685     }
2686     *p = '\0';
2687     }
2688    
2689     /*
2690     * cidr_limit_reached
2691     *
2692 db 126 * inputs - int flag allowing exemption of limits
2693 adx 30 * - pointer to the ip to be added
2694     * - pointer to the class
2695     * output - non zero if limit reached
2696     * 0 if limit not reached
2697     * side effects -
2698     */
2699     static int
2700 db 126 cidr_limit_reached(int exempt,
2701 adx 30 struct irc_ssaddr *ip, struct ClassItem *aclass)
2702     {
2703     dlink_node *ptr = NULL;
2704     struct CidrItem *cidr;
2705    
2706     if (NumberPerCidr(aclass) <= 0)
2707     return 0;
2708    
2709     if (ip->ss.ss_family == AF_INET)
2710     {
2711     if (CidrBitlenIPV4(aclass) <= 0)
2712     return 0;
2713    
2714     DLINK_FOREACH(ptr, aclass->list_ipv4.head)
2715     {
2716     cidr = ptr->data;
2717     if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
2718     {
2719 db 126 if (!exempt && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
2720 adx 30 return -1;
2721     cidr->number_on_this_cidr++;
2722     return 0;
2723     }
2724     }
2725     cidr = MyMalloc(sizeof(struct CidrItem));
2726     cidr->number_on_this_cidr = 1;
2727     cidr->mask = *ip;
2728     mask_addr(&cidr->mask, CidrBitlenIPV4(aclass));
2729     dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
2730     }
2731     #ifdef IPV6
2732     else if (CidrBitlenIPV6(aclass) > 0)
2733     {
2734     DLINK_FOREACH(ptr, aclass->list_ipv6.head)
2735     {
2736     cidr = ptr->data;
2737     if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
2738     {
2739 db 126 if (!exempt && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
2740 adx 30 return -1;
2741     cidr->number_on_this_cidr++;
2742     return 0;
2743     }
2744     }
2745     cidr = MyMalloc(sizeof(struct CidrItem));
2746     cidr->number_on_this_cidr = 1;
2747     cidr->mask = *ip;
2748     mask_addr(&cidr->mask, CidrBitlenIPV6(aclass));
2749     dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
2750     }
2751     #endif
2752     return 0;
2753     }
2754    
2755     /*
2756     * remove_from_cidr_check
2757     *
2758     * inputs - pointer to the ip to be removed
2759     * - pointer to the class
2760     * output - NONE
2761     * side effects -
2762     */
2763     static void
2764     remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
2765     {
2766     dlink_node *ptr = NULL;
2767     dlink_node *next_ptr = NULL;
2768     struct CidrItem *cidr;
2769    
2770     if (NumberPerCidr(aclass) == 0)
2771     return;
2772    
2773     if (ip->ss.ss_family == AF_INET)
2774     {
2775     if (CidrBitlenIPV4(aclass) <= 0)
2776     return;
2777    
2778     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
2779     {
2780     cidr = ptr->data;
2781     if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
2782     {
2783     cidr->number_on_this_cidr--;
2784     if (cidr->number_on_this_cidr == 0)
2785     {
2786     dlinkDelete(ptr, &aclass->list_ipv4);
2787     MyFree(cidr);
2788     return;
2789     }
2790     }
2791     }
2792     }
2793     #ifdef IPV6
2794     else if (CidrBitlenIPV6(aclass) > 0)
2795     {
2796     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
2797     {
2798     cidr = ptr->data;
2799     if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
2800     {
2801     cidr->number_on_this_cidr--;
2802     if (cidr->number_on_this_cidr == 0)
2803     {
2804     dlinkDelete(ptr, &aclass->list_ipv6);
2805     MyFree(cidr);
2806     return;
2807     }
2808     }
2809     }
2810     }
2811     #endif
2812     }
2813    
2814     static void
2815 db 126 rebuild_cidr_list(int aftype, struct ClassItem *oldcl, struct ClassItem *newcl,
2816 adx 30 dlink_list *old_list, dlink_list *new_list, int changed)
2817     {
2818     dlink_node *ptr;
2819     struct Client *client_p;
2820    
2821     if (!changed)
2822     {
2823     *new_list = *old_list;
2824     old_list->head = old_list->tail = NULL;
2825     old_list->length = 0;
2826     return;
2827     }
2828    
2829     DLINK_FOREACH(ptr, local_client_list.head)
2830     {
2831     client_p = ptr->data;
2832     if (client_p->localClient->aftype != aftype)
2833     continue;
2834 db 126 if (client_p->localClient->class == NULL)
2835 adx 30 continue;
2836    
2837 db 126 if (client_p->localClient->class == oldcl)
2838 db 101 cidr_limit_reached(1, &client_p->localClient->ip, newcl);
2839 adx 30 }
2840     }
2841    
2842     /*
2843     * rebuild_cidr_class
2844     *
2845     * inputs - pointer to old conf
2846     * - pointer to new_class
2847     * output - none
2848     * side effects - rebuilds the class link list of cidr blocks
2849     */
2850     void
2851 db 126 rebuild_cidr_class(struct ClassItem *old_class, struct ClassItem *new_class)
2852 adx 30 {
2853     if (NumberPerCidr(old_class) > 0 && NumberPerCidr(new_class) > 0)
2854     {
2855     if (CidrBitlenIPV4(old_class) > 0 && CidrBitlenIPV4(new_class) > 0)
2856 db 126 rebuild_cidr_list(AF_INET, old_class, new_class,
2857 adx 30 &old_class->list_ipv4, &new_class->list_ipv4,
2858     CidrBitlenIPV4(old_class) != CidrBitlenIPV4(new_class));
2859    
2860     #ifdef IPV6
2861     if (CidrBitlenIPV6(old_class) > 0 && CidrBitlenIPV6(new_class) > 0)
2862 db 126 rebuild_cidr_list(AF_INET6, old_class, new_class,
2863 adx 30 &old_class->list_ipv6, &new_class->list_ipv6,
2864     CidrBitlenIPV6(old_class) != CidrBitlenIPV6(new_class));
2865     #endif
2866     }
2867    
2868     destroy_cidr_class(old_class);
2869     }
2870    
2871     /*
2872     * destroy_cidr_list
2873     *
2874     * inputs - pointer to class dlink list of cidr blocks
2875     * output - none
2876     * side effects - completely destroys the class link list of cidr blocks
2877     */
2878     static void
2879     destroy_cidr_list(dlink_list *list)
2880     {
2881     dlink_node *ptr = NULL;
2882     dlink_node *next_ptr = NULL;
2883     struct CidrItem *cidr;
2884    
2885     DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
2886     {
2887     cidr = ptr->data;
2888     dlinkDelete(ptr, list);
2889     MyFree(cidr);
2890     }
2891     }
2892    
2893     /*
2894     * destroy_cidr_class
2895     *
2896     * inputs - pointer to class
2897     * output - none
2898     * side effects - completely destroys the class link list of cidr blocks
2899     */
2900     static void
2901     destroy_cidr_class(struct ClassItem *aclass)
2902     {
2903     destroy_cidr_list(&aclass->list_ipv4);
2904     destroy_cidr_list(&aclass->list_ipv6);
2905     }
2906 db 126
2907    

Properties

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