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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 575 - (show annotations)
Mon May 1 11:41:09 2006 UTC (14 years, 3 months ago) by michael
File MIME type: text/x-chdr
File size: 101575 byte(s)
- Fixed a bunch of compile warnings

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