ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/s_conf.c
Revision: 357
Committed: Thu Jan 5 16:06:45 2006 UTC (20 years, 6 months ago) by michael
Content type: text/x-csrc
File size: 73599 byte(s)
Log Message:
- Mainly re-wrote split_nuh() to fix a regexp kline bug where we would cut off
  the user portion after 9 chars, but also to be a bit more flexible when we
  have to deal with different user/host name lengths.
- Re-wrote m_capture() to use split_nuh()

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

Properties

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