ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1368
Committed: Wed Apr 25 16:42:06 2012 UTC (11 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 98276 byte(s)
Log Message:
- Remove temporary RKLINES/RXLINES leftovers

File Contents

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

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision