ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1294
Committed: Wed Feb 22 20:48:30 2012 UTC (12 years, 1 month ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/s_conf.c
File size: 100446 byte(s)
Log Message:
- Add user mode +H which simply hides operator status to other users.
  This solution replaces current method of hidding operator status where the
  admin mode is not sent to other servers unless hidden_administrator is disabled.
- m_who() now takes care whether an operator is hidden or not

File Contents

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

Properties

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