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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1302 - (show annotations)
Wed Mar 21 17:48:54 2012 UTC (10 years, 5 months ago) by michael
File MIME type: text/x-chdr
File size: 99420 byte(s)
- remove servlink in preparation for tls links/compression

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