/[svn]/ircd-hybrid-7.2/src/s_conf.c
ViewVC logotype

Contents of /ircd-hybrid-7.2/src/s_conf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1001 - (show annotations)
Sat Aug 29 22:44:44 2009 UTC (11 years, 6 months ago) by michael
File MIME type: text/x-chdr
File size: 100164 byte(s)
- remove half done and broken win32 support

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