/[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 1175 - (show annotations)
Sun Aug 14 10:47:48 2011 UTC (8 years, 10 months ago) by michael
File MIME type: text/x-chdr
File size: 100397 byte(s)
- several fixes to services compatibility mode

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