ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1219
Committed: Sun Sep 18 09:02:38 2011 UTC (15 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/s_conf.c
File size: 100407 byte(s)
Log Message:
- Start cleaning up macros in client.h. Replace several ClientHasSomeCoolFlag()
with simple HasFlag/HasUMode macros.

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

Properties

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