ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/conf.c
Revision: 1302
Committed: Wed Mar 21 17:48:54 2012 UTC (12 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/s_conf.c
File size: 99420 byte(s)
Log Message:
- remove servlink in preparation for tls links/compression

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

Properties

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