ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1303
Committed: Fri Mar 23 10:52:19 2012 UTC (12 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/s_conf.c
File size: 99468 byte(s)
Log Message:
- Implement basic tls connections for server-server links

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

Properties

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