ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1243
Committed: Fri Sep 30 10:47:53 2011 UTC (13 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/s_conf.c
File size: 100370 byte(s)
Log Message:
- move content of msg.h, ircd_handler.h and handlers.h into parse.h and
  remove headers accordingly
- killed common.h
- remove m_killhost.c and m_flags.c from contrib/
- sort out unused header includes here and there

File Contents

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

Properties

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