/[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 1303 - (show annotations)
Fri Mar 23 10:52:19 2012 UTC (10 years, 4 months ago) by michael
File MIME type: text/x-chdr
File size: 99468 byte(s)
- Implement basic tls connections for server-server links

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