ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1628
Committed: Thu Nov 1 21:08:56 2012 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 88730 byte(s)
Log Message:
- flesh out new *line database handling
- simplify temporary bans

File Contents

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

Properties

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