ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1377
Committed: Mon Apr 30 19:35:16 2012 UTC (11 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 95886 byte(s)
Log Message:
- Remove all Class related #defines like MaxTotal, MaxSendq, etc.
  All they do is lead to confusion.

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

Properties

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