ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1381
Committed: Tue May 1 08:21:27 2012 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 95695 byte(s)
Log Message:
- conf.c: remove CLIENT_CONF leftovers in clear_out_old_conf()
  clear_out_address_conf() already does the deal.

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 == XLINE_TYPE ||
2506 conf->type == RXLINE_TYPE ||
2507 conf->type == RKLINE_TYPE)
2508 {
2509 /* temporary (r)xlines are also on
2510 * the (r)xconf items list */
2511 if (conf->flags & CONF_FLAGS_TEMPORARY)
2512 continue;
2513
2514 delete_conf_item(conf);
2515 }
2516 else
2517 {
2518 if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2519 {
2520 match_item = map_to_conf(conf);
2521 if (match_item->ref_count <= 0)
2522 delete_conf_item(conf);
2523 else
2524 {
2525 match_item->illegal = 1;
2526 dlinkDelete(&conf->node, *iterator);
2527 }
2528 }
2529 else
2530 delete_conf_item(conf);
2531 }
2532 }
2533 }
2534
2535 /*
2536 * don't delete the class table, rather mark all entries
2537 * for deletion. The table is cleaned up by check_class. - avalon
2538 */
2539 DLINK_FOREACH(ptr, class_items.head)
2540 {
2541 cltmp = map_to_conf(ptr->data);
2542
2543 if (ptr != class_items.tail) /* never mark the "default" class */
2544 cltmp->active = 0;
2545 }
2546
2547 clear_out_address_conf();
2548
2549 /* clean out module paths */
2550 mod_clear_paths();
2551
2552 /* clean out ServerInfo */
2553 MyFree(ServerInfo.description);
2554 ServerInfo.description = NULL;
2555 MyFree(ServerInfo.network_name);
2556 ServerInfo.network_name = NULL;
2557 MyFree(ServerInfo.network_desc);
2558 ServerInfo.network_desc = NULL;
2559 MyFree(ConfigFileEntry.egdpool_path);
2560 ConfigFileEntry.egdpool_path = NULL;
2561 #ifdef HAVE_LIBCRYPTO
2562 if (ServerInfo.rsa_private_key != NULL)
2563 {
2564 RSA_free(ServerInfo.rsa_private_key);
2565 ServerInfo.rsa_private_key = NULL;
2566 }
2567
2568 MyFree(ServerInfo.rsa_private_key_file);
2569 ServerInfo.rsa_private_key_file = NULL;
2570
2571 if (ServerInfo.server_ctx)
2572 SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
2573 SSL_OP_NO_SSLv3|
2574 SSL_OP_NO_TLSv1);
2575 if (ServerInfo.client_ctx)
2576 SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
2577 SSL_OP_NO_SSLv3|
2578 SSL_OP_NO_TLSv1);
2579 #endif
2580
2581 /* clean out old resvs from the conf */
2582 clear_conf_resv();
2583
2584 /* clean out AdminInfo */
2585 MyFree(AdminInfo.name);
2586 AdminInfo.name = NULL;
2587 MyFree(AdminInfo.email);
2588 AdminInfo.email = NULL;
2589 MyFree(AdminInfo.description);
2590 AdminInfo.description = NULL;
2591
2592 /* operator{} and class{} blocks are freed above */
2593 /* clean out listeners */
2594 close_listeners();
2595
2596 /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2597 * exempt{} and gecos{} blocks are freed above too
2598 */
2599
2600 /* clean out general */
2601 MyFree(ConfigFileEntry.service_name);
2602 ConfigFileEntry.service_name = NULL;
2603
2604 delete_isupport("INVEX");
2605 delete_isupport("EXCEPTS");
2606 }
2607
2608 /* flush_deleted_I_P()
2609 *
2610 * inputs - none
2611 * output - none
2612 * side effects - This function removes I/P conf items
2613 */
2614 static void
2615 flush_deleted_I_P(void)
2616 {
2617 dlink_node *ptr;
2618 dlink_node *next_ptr;
2619 struct ConfItem *conf;
2620 struct AccessItem *aconf;
2621 dlink_list * free_items [] = {
2622 &server_items, &oconf_items, NULL
2623 };
2624 dlink_list ** iterator = free_items; /* C is dumb */
2625
2626 /* flush out deleted I and P lines
2627 * although still in use.
2628 */
2629 for (; *iterator != NULL; iterator++)
2630 {
2631 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2632 {
2633 conf = ptr->data;
2634 aconf = (struct AccessItem *)map_to_conf(conf);
2635
2636 if (IsConfIllegal(aconf))
2637 {
2638 dlinkDelete(ptr, *iterator);
2639
2640 if (aconf->clients == 0)
2641 delete_conf_item(conf);
2642 }
2643 }
2644 }
2645 }
2646
2647 /* get_conf_name()
2648 *
2649 * inputs - type of conf file to return name of file for
2650 * output - pointer to filename for type of conf
2651 * side effects - none
2652 */
2653 const char *
2654 get_conf_name(ConfType type)
2655 {
2656 switch (type)
2657 {
2658 case CONF_TYPE:
2659 return ConfigFileEntry.configfile;
2660 break;
2661 case KLINE_TYPE:
2662 return ConfigFileEntry.klinefile;
2663 break;
2664 case RKLINE_TYPE:
2665 return ConfigFileEntry.rklinefile;
2666 break;
2667 case DLINE_TYPE:
2668 return ConfigFileEntry.dlinefile;
2669 break;
2670 case XLINE_TYPE:
2671 return ConfigFileEntry.xlinefile;
2672 break;
2673 case RXLINE_TYPE:
2674 return ConfigFileEntry.rxlinefile;
2675 break;
2676 case CRESV_TYPE:
2677 return ConfigFileEntry.cresvfile;
2678 break;
2679 case NRESV_TYPE:
2680 return ConfigFileEntry.nresvfile;
2681 break;
2682 case GLINE_TYPE:
2683 return ConfigFileEntry.glinefile;
2684 break;
2685
2686 default:
2687 return NULL; /* This should NEVER HAPPEN since we call this function
2688 only with the above values, this will cause us to core
2689 at some point if this happens so we know where it was */
2690 }
2691 }
2692
2693 #define BAD_PING (-1)
2694
2695 /* get_conf_ping()
2696 *
2697 * inputs - pointer to struct AccessItem
2698 * - pointer to a variable that receives ping warning time
2699 * output - ping frequency
2700 * side effects - NONE
2701 */
2702 static int
2703 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2704 {
2705 struct ClassItem *aclass;
2706 struct AccessItem *aconf;
2707
2708 if (conf != NULL)
2709 {
2710 aconf = (struct AccessItem *)map_to_conf(conf);
2711 if (aconf->class_ptr != NULL)
2712 {
2713 aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2714 *pingwarn = aclass->ping_warning;
2715 return aclass->ping_freq;
2716 }
2717 }
2718
2719 return BAD_PING;
2720 }
2721
2722 /* get_client_class()
2723 *
2724 * inputs - pointer to client struct
2725 * output - pointer to name of class
2726 * side effects - NONE
2727 */
2728 const char *
2729 get_client_class(struct Client *target_p)
2730 {
2731 dlink_node *ptr;
2732 struct ConfItem *conf;
2733 struct AccessItem *aconf;
2734
2735 if (target_p != NULL && !IsMe(target_p) &&
2736 target_p->localClient->confs.head != NULL)
2737 {
2738 DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2739 {
2740 conf = ptr->data;
2741
2742 if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2743 conf->type == OPER_TYPE)
2744 {
2745 aconf = (struct AccessItem *) map_to_conf(conf);
2746 if (aconf->class_ptr != NULL)
2747 return aconf->class_ptr->name;
2748 }
2749 }
2750 }
2751
2752 return "default";
2753 }
2754
2755 /* get_client_ping()
2756 *
2757 * inputs - pointer to client struct
2758 * - pointer to a variable that receives ping warning time
2759 * output - ping frequency
2760 * side effects - NONE
2761 */
2762 int
2763 get_client_ping(struct Client *target_p, int *pingwarn)
2764 {
2765 int ping;
2766 struct ConfItem *conf;
2767 dlink_node *nlink;
2768
2769 if (target_p->localClient->confs.head != NULL)
2770 DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2771 {
2772 conf = nlink->data;
2773
2774 if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2775 (conf->type == OPER_TYPE))
2776 {
2777 ping = get_conf_ping(conf, pingwarn);
2778 if (ping > 0)
2779 return ping;
2780 }
2781 }
2782
2783 *pingwarn = 0;
2784 return DEFAULT_PINGFREQUENCY;
2785 }
2786
2787 /* find_class()
2788 *
2789 * inputs - string name of class
2790 * output - corresponding Class pointer
2791 * side effects - NONE
2792 */
2793 struct ConfItem *
2794 find_class(const char *classname)
2795 {
2796 struct ConfItem *conf;
2797
2798 if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2799 return conf;
2800
2801 return class_default;
2802 }
2803
2804 /* check_class()
2805 *
2806 * inputs - NONE
2807 * output - NONE
2808 * side effects -
2809 */
2810 void
2811 check_class(void)
2812 {
2813 dlink_node *ptr = NULL, *next_ptr = NULL;
2814
2815 DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2816 {
2817 struct ClassItem *aclass = map_to_conf(ptr->data);
2818
2819 if (!aclass->active && !aclass->curr_user_count)
2820 {
2821 destroy_cidr_class(aclass);
2822 delete_conf_item(ptr->data);
2823 }
2824 }
2825 }
2826
2827 /* init_class()
2828 *
2829 * inputs - NONE
2830 * output - NONE
2831 * side effects -
2832 */
2833 void
2834 init_class(void)
2835 {
2836 struct ClassItem *aclass;
2837
2838 class_default = make_conf_item(CLASS_TYPE);
2839
2840 aclass = map_to_conf(class_default);
2841 aclass->active = 1;
2842 DupString(class_default->name, "default");
2843 aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
2844 aclass->ping_freq = DEFAULT_PINGFREQUENCY;
2845 aclass->max_total = MAXIMUM_LINKS_DEFAULT;
2846 aclass->max_sendq = DEFAULT_SENDQ;
2847
2848 client_check_cb = register_callback("check_client", check_client);
2849 }
2850
2851 /* get_sendq()
2852 *
2853 * inputs - pointer to client
2854 * output - sendq for this client as found from its class
2855 * side effects - NONE
2856 */
2857 unsigned int
2858 get_sendq(struct Client *client_p)
2859 {
2860 unsigned int sendq = DEFAULT_SENDQ;
2861 dlink_node *ptr;
2862 struct ConfItem *conf;
2863 struct ConfItem *class_conf;
2864 struct ClassItem *aclass;
2865 struct AccessItem *aconf;
2866
2867 if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2868 {
2869 DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2870 {
2871 conf = ptr->data;
2872 if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2873 || (conf->type == CLIENT_TYPE))
2874 {
2875 aconf = (struct AccessItem *)map_to_conf(conf);
2876 if ((class_conf = aconf->class_ptr) == NULL)
2877 continue;
2878 aclass = (struct ClassItem *)map_to_conf(class_conf);
2879 sendq = aclass->max_sendq;
2880 return sendq;
2881 }
2882 }
2883 }
2884 /* XXX return a default?
2885 * if here, then there wasn't an attached conf with a sendq
2886 * that is very bad -Dianora
2887 */
2888 return DEFAULT_SENDQ;
2889 }
2890
2891 /* conf_add_class_to_conf()
2892 *
2893 * inputs - pointer to config item
2894 * output - NONE
2895 * side effects - Add a class pointer to a conf
2896 */
2897 void
2898 conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
2899 {
2900 struct AccessItem *aconf = map_to_conf(conf);
2901 struct ClassItem *class = NULL;
2902
2903 if (class_name == NULL)
2904 {
2905 aconf->class_ptr = class_default;
2906
2907 if (conf->type == CLIENT_TYPE)
2908 sendto_realops_flags(UMODE_ALL, L_ALL,
2909 "Warning *** Defaulting to default class for %s@%s",
2910 aconf->user, aconf->host);
2911 else
2912 sendto_realops_flags(UMODE_ALL, L_ALL,
2913 "Warning *** Defaulting to default class for %s",
2914 conf->name);
2915 }
2916 else
2917 aconf->class_ptr = find_class(class_name);
2918
2919 if (aconf->class_ptr)
2920 class = map_to_conf(aconf->class_ptr);
2921
2922 if (aconf->class_ptr == NULL || !class->active)
2923 {
2924 if (conf->type == CLIENT_TYPE)
2925 sendto_realops_flags(UMODE_ALL, L_ALL,
2926 "Warning *** Defaulting to default class for %s@%s",
2927 aconf->user, aconf->host);
2928 else
2929 sendto_realops_flags(UMODE_ALL, L_ALL,
2930 "Warning *** Defaulting to default class for %s",
2931 conf->name);
2932 aconf->class_ptr = class_default;
2933 }
2934 }
2935
2936 /* conf_add_server()
2937 *
2938 * inputs - pointer to config item
2939 * - pointer to link count already on this conf
2940 * output - NONE
2941 * side effects - Add a connect block
2942 */
2943 int
2944 conf_add_server(struct ConfItem *conf, const char *class_name)
2945 {
2946 struct AccessItem *aconf = map_to_conf(conf);
2947
2948 conf_add_class_to_conf(conf, class_name);
2949
2950 if (!aconf->host || !conf->name)
2951 {
2952 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
2953 ilog(LOG_TYPE_IRCD, "Bad connect block");
2954 return -1;
2955 }
2956
2957 if (EmptyString(aconf->passwd))
2958 {
2959 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
2960 conf->name);
2961 ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
2962 return -1;
2963 }
2964
2965 lookup_confhost(conf);
2966
2967 return 0;
2968 }
2969
2970 /* yyerror()
2971 *
2972 * inputs - message from parser
2973 * output - NONE
2974 * side effects - message to opers and log file entry is made
2975 */
2976 void
2977 yyerror(const char *msg)
2978 {
2979 char newlinebuf[IRCD_BUFSIZE];
2980
2981 if (conf_parser_ctx.pass != 1)
2982 return;
2983
2984 strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
2985 sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
2986 conffilebuf, lineno + 1, msg, newlinebuf);
2987 ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
2988 conffilebuf, lineno + 1, msg, newlinebuf);
2989 }
2990
2991 /*
2992 * valid_tkline()
2993 *
2994 * inputs - pointer to ascii string to check
2995 * - whether the specified time is in seconds or minutes
2996 * output - -1 not enough parameters
2997 * - 0 if not an integer number, else the number
2998 * side effects - none
2999 * Originally written by Dianora (Diane, db@db.net)
3000 */
3001 time_t
3002 valid_tkline(const char *p, int minutes)
3003 {
3004 time_t result = 0;
3005
3006 for (; *p; ++p)
3007 {
3008 if (!IsDigit(*p))
3009 return 0;
3010
3011 result *= 10;
3012 result += ((*p) & 0xF);
3013 }
3014
3015 /*
3016 * In the degenerate case where oper does a /quote kline 0 user@host :reason
3017 * i.e. they specifically use 0, I am going to return 1 instead
3018 * as a return value of non-zero is used to flag it as a temporary kline
3019 */
3020 if (result == 0)
3021 result = 1;
3022
3023 /*
3024 * If the incoming time is in seconds convert it to minutes for the purpose
3025 * of this calculation
3026 */
3027 if (!minutes)
3028 result = result / (time_t)60;
3029
3030 if (result > MAX_TDKLINE_TIME)
3031 result = MAX_TDKLINE_TIME;
3032
3033 result = result * (time_t)60; /* turn it into seconds */
3034
3035 return result;
3036 }
3037
3038 /* valid_wild_card()
3039 *
3040 * input - pointer to client
3041 * - int flag, 0 for no warning oper 1 for warning oper
3042 * - count of following varargs to check
3043 * output - 0 if not valid, 1 if valid
3044 * side effects - NOTICE is given to source_p if warn is 1
3045 */
3046 int
3047 valid_wild_card(struct Client *source_p, int warn, int count, ...)
3048 {
3049 char *p;
3050 char tmpch;
3051 int nonwild = 0;
3052 va_list args;
3053
3054 /*
3055 * Now we must check the user and host to make sure there
3056 * are at least NONWILDCHARS non-wildcard characters in
3057 * them, otherwise assume they are attempting to kline
3058 * *@* or some variant of that. This code will also catch
3059 * people attempting to kline *@*.tld, as long as NONWILDCHARS
3060 * is greater than 3. In that case, there are only 3 non-wild
3061 * characters (tld), so if NONWILDCHARS is 4, the kline will
3062 * be disallowed.
3063 * -wnder
3064 */
3065
3066 va_start(args, count);
3067
3068 while (count--)
3069 {
3070 p = va_arg(args, char *);
3071 if (p == NULL)
3072 continue;
3073
3074 while ((tmpch = *p++))
3075 {
3076 if (!IsKWildChar(tmpch))
3077 {
3078 /*
3079 * If we find enough non-wild characters, we can
3080 * break - no point in searching further.
3081 */
3082 if (++nonwild >= ConfigFileEntry.min_nonwildcard)
3083 return 1;
3084 }
3085 }
3086 }
3087
3088 if (warn)
3089 sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
3090 me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
3091 return 0;
3092 }
3093
3094 /* XXX should this go into a separate file ? -Dianora */
3095 /* parse_aline
3096 *
3097 * input - pointer to cmd name being used
3098 * - pointer to client using cmd
3099 * - parc parameter count
3100 * - parv[] list of parameters to parse
3101 * - parse_flags bit map of things to test
3102 * - pointer to user or string to parse into
3103 * - pointer to host or NULL to parse into if non NULL
3104 * - pointer to optional tkline time or NULL
3105 * - pointer to target_server to parse into if non NULL
3106 * - pointer to reason to parse into
3107 *
3108 * output - 1 if valid, -1 if not valid
3109 * side effects - A generalised k/d/x etc. line parser,
3110 * "ALINE [time] user@host|string [ON] target :reason"
3111 * will parse returning a parsed user, host if
3112 * h_p pointer is non NULL, string otherwise.
3113 * if tkline_time pointer is non NULL a tk line will be set
3114 * to non zero if found.
3115 * if tkline_time pointer is NULL and tk line is found,
3116 * error is reported.
3117 * if target_server is NULL and an "ON" is found error
3118 * is reported.
3119 * if reason pointer is NULL ignore pointer,
3120 * this allows use of parse_a_line in unkline etc.
3121 *
3122 * - Dianora
3123 */
3124 int
3125 parse_aline(const char *cmd, struct Client *source_p,
3126 int parc, char **parv,
3127 int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
3128 char **target_server, char **reason)
3129 {
3130 int found_tkline_time=0;
3131 static char def_reason[] = "No Reason";
3132 static char user[USERLEN*4+1];
3133 static char host[HOSTLEN*4+1];
3134
3135 parv++;
3136 parc--;
3137
3138 found_tkline_time = valid_tkline(*parv, TK_MINUTES);
3139
3140 if (found_tkline_time != 0)
3141 {
3142 parv++;
3143 parc--;
3144
3145 if (tkline_time != NULL)
3146 *tkline_time = found_tkline_time;
3147 else
3148 {
3149 sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3150 me.name, source_p->name, cmd);
3151 return -1;
3152 }
3153 }
3154
3155 if (parc == 0)
3156 {
3157 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3158 me.name, source_p->name, cmd);
3159 return -1;
3160 }
3161
3162 if (h_p == NULL)
3163 *up_p = *parv;
3164 else
3165 {
3166 if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
3167 return -1;
3168
3169 *up_p = user;
3170 *h_p = host;
3171 }
3172
3173 parc--;
3174 parv++;
3175
3176 if (parc != 0)
3177 {
3178 if (irccmp(*parv, "ON") == 0)
3179 {
3180 parc--;
3181 parv++;
3182
3183 if (target_server == NULL)
3184 {
3185 sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
3186 me.name, source_p->name, cmd);
3187 return -1;
3188 }
3189
3190 if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
3191 {
3192 sendto_one(source_p, form_str(ERR_NOPRIVS),
3193 me.name, source_p->name, "remoteban");
3194 return -1;
3195 }
3196
3197 if (parc == 0 || EmptyString(*parv))
3198 {
3199 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3200 me.name, source_p->name, cmd);
3201 return -1;
3202 }
3203
3204 *target_server = *parv;
3205 parc--;
3206 parv++;
3207 }
3208 else
3209 {
3210 /* Make sure target_server *is* NULL if no ON server found
3211 * caller probably NULL'd it first, but no harm to do it again -db
3212 */
3213 if (target_server != NULL)
3214 *target_server = NULL;
3215 }
3216 }
3217
3218 if (h_p != NULL)
3219 {
3220 if (strchr(user, '!') != NULL)
3221 {
3222 sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3223 me.name, source_p->name);
3224 return -1;
3225 }
3226
3227 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 2, *up_p, *h_p))
3228 return -1;
3229 }
3230 else
3231 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 1, *up_p))
3232 return -1;
3233
3234 if (reason != NULL)
3235 {
3236 if (parc != 0 && !EmptyString(*parv))
3237 {
3238 *reason = *parv;
3239 if (!valid_comment(source_p, *reason, 1))
3240 return -1;
3241 }
3242 else
3243 *reason = def_reason;
3244 }
3245
3246 return 1;
3247 }
3248
3249 /* find_user_host()
3250 *
3251 * inputs - pointer to client placing kline
3252 * - pointer to user_host_or_nick
3253 * - pointer to user buffer
3254 * - pointer to host buffer
3255 * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
3256 * side effects -
3257 */
3258 static int
3259 find_user_host(struct Client *source_p, char *user_host_or_nick,
3260 char *luser, char *lhost, unsigned int flags)
3261 {
3262 struct Client *target_p = NULL;
3263 char *hostp = NULL;
3264
3265 if (lhost == NULL)
3266 {
3267 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
3268 return 1;
3269 }
3270
3271 if ((hostp = strchr(user_host_or_nick, '@')) || *user_host_or_nick == '*')
3272 {
3273 /* Explicit user@host mask given */
3274
3275 if (hostp != NULL) /* I'm a little user@host */
3276 {
3277 *(hostp++) = '\0'; /* short and squat */
3278 if (*user_host_or_nick)
3279 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
3280 else
3281 strcpy(luser, "*");
3282 if (*hostp)
3283 strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
3284 else
3285 strcpy(lhost, "*");
3286 }
3287 else
3288 {
3289 luser[0] = '*'; /* no @ found, assume its *@somehost */
3290 luser[1] = '\0';
3291 strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
3292 }
3293
3294 return 1;
3295 }
3296 else if (!(flags & NOUSERLOOKUP))
3297 {
3298 /* Try to find user@host mask from nick */
3299 /* Okay to use source_p as the first param, because source_p == client_p */
3300 if ((target_p =
3301 find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
3302 return 0;
3303
3304 if (IsExemptKline(target_p))
3305 {
3306 if (!IsServer(source_p))
3307 sendto_one(source_p,
3308 ":%s NOTICE %s :%s is E-lined",
3309 me.name, source_p->name, target_p->name);
3310 return 0;
3311 }
3312
3313 /*
3314 * turn the "user" bit into "*user", blow away '~'
3315 * if found in original user name (non-idented)
3316 */
3317 strlcpy(luser, target_p->username, USERLEN*4 + 1);
3318
3319 if (target_p->username[0] == '~')
3320 luser[0] = '*';
3321
3322 if (target_p->sockhost[0] == '\0' ||
3323 (target_p->sockhost[0] == '0' && target_p->sockhost[1] == '\0'))
3324 strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
3325 else
3326 strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
3327 return 1;
3328 }
3329
3330 return 0;
3331 }
3332
3333 /* valid_comment()
3334 *
3335 * inputs - pointer to client
3336 * - pointer to comment
3337 * output - 0 if no valid comment,
3338 * - 1 if valid
3339 * side effects - truncates reason where necessary
3340 */
3341 int
3342 valid_comment(struct Client *source_p, char *comment, int warn)
3343 {
3344 if (strchr(comment, '"'))
3345 {
3346 if (warn)
3347 sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3348 me.name, source_p->name);
3349 return 0;
3350 }
3351
3352 if (strlen(comment) > REASONLEN)
3353 comment[REASONLEN-1] = '\0';
3354
3355 return 1;
3356 }
3357
3358 /* match_conf_password()
3359 *
3360 * inputs - pointer to given password
3361 * - pointer to Conf
3362 * output - 1 or 0 if match
3363 * side effects - none
3364 */
3365 int
3366 match_conf_password(const char *password, const struct AccessItem *aconf)
3367 {
3368 const char *encr = NULL;
3369
3370 if (password == NULL || aconf->passwd == NULL)
3371 return 0;
3372
3373 if (aconf->flags & CONF_FLAGS_ENCRYPTED)
3374 {
3375 /* use first two chars of the password they send in as salt */
3376 /* If the password in the conf is MD5, and ircd is linked
3377 * to scrypt on FreeBSD, or the standard crypt library on
3378 * glibc Linux, then this code will work fine on generating
3379 * the proper encrypted hash for comparison.
3380 */
3381 if (*aconf->passwd)
3382 encr = crypt(password, aconf->passwd);
3383 else
3384 encr = "";
3385 }
3386 else
3387 encr = password;
3388
3389 return !strcmp(encr, aconf->passwd);
3390 }
3391
3392 /*
3393 * cluster_a_line
3394 *
3395 * inputs - client sending the cluster
3396 * - command name "KLINE" "XLINE" etc.
3397 * - capab -- CAP_KLN etc. from s_serv.h
3398 * - cluster type -- CLUSTER_KLINE etc. from conf.h
3399 * - pattern and args to send along
3400 * output - none
3401 * side effects - Take source_p send the pattern with args given
3402 * along to all servers that match capab and cluster type
3403 */
3404 void
3405 cluster_a_line(struct Client *source_p, const char *command,
3406 int capab, int cluster_type, const char *pattern, ...)
3407 {
3408 va_list args;
3409 char buffer[IRCD_BUFSIZE];
3410 const dlink_node *ptr = NULL;
3411
3412 va_start(args, pattern);
3413 vsnprintf(buffer, sizeof(buffer), pattern, args);
3414 va_end(args);
3415
3416 DLINK_FOREACH(ptr, cluster_items.head)
3417 {
3418 const struct ConfItem *conf = ptr->data;
3419
3420 if (conf->flags & cluster_type)
3421 sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
3422 "%s %s %s", command, conf->name, buffer);
3423 }
3424 }
3425
3426 /*
3427 * split_nuh
3428 *
3429 * inputs - pointer to original mask (modified in place)
3430 * - pointer to pointer where nick should go
3431 * - pointer to pointer where user should go
3432 * - pointer to pointer where host should go
3433 * output - NONE
3434 * side effects - mask is modified in place
3435 * If nick pointer is NULL, ignore writing to it
3436 * this allows us to use this function elsewhere.
3437 *
3438 * mask nick user host
3439 * ---------------------- ------- ------- ------
3440 * Dianora!db@db.net Dianora db db.net
3441 * Dianora Dianora * *
3442 * db.net * * db.net
3443 * OR if nick pointer is NULL
3444 * Dianora - * Dianora
3445 * Dianora! Dianora * *
3446 * Dianora!@ Dianora * *
3447 * Dianora!db Dianora db *
3448 * Dianora!@db.net Dianora * db.net
3449 * db@db.net * db db.net
3450 * !@ * * *
3451 * @ * * *
3452 * ! * * *
3453 */
3454 void
3455 split_nuh(struct split_nuh_item *const iptr)
3456 {
3457 char *p = NULL, *q = NULL;
3458
3459 if (iptr->nickptr)
3460 strlcpy(iptr->nickptr, "*", iptr->nicksize);
3461 if (iptr->userptr)
3462 strlcpy(iptr->userptr, "*", iptr->usersize);
3463 if (iptr->hostptr)
3464 strlcpy(iptr->hostptr, "*", iptr->hostsize);
3465
3466 if ((p = strchr(iptr->nuhmask, '!')))
3467 {
3468 *p = '\0';
3469
3470 if (iptr->nickptr && *iptr->nuhmask != '\0')
3471 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3472
3473 if ((q = strchr(++p, '@'))) {
3474 *q++ = '\0';
3475
3476 if (*p != '\0')
3477 strlcpy(iptr->userptr, p, iptr->usersize);
3478
3479 if (*q != '\0')
3480 strlcpy(iptr->hostptr, q, iptr->hostsize);
3481 }
3482 else
3483 {
3484 if (*p != '\0')
3485 strlcpy(iptr->userptr, p, iptr->usersize);
3486 }
3487 }
3488 else
3489 {
3490 /* No ! found so lets look for a user@host */
3491 if ((p = strchr(iptr->nuhmask, '@')))
3492 {
3493 /* if found a @ */
3494 *p++ = '\0';
3495
3496 if (*iptr->nuhmask != '\0')
3497 strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
3498
3499 if (*p != '\0')
3500 strlcpy(iptr->hostptr, p, iptr->hostsize);
3501 }
3502 else
3503 {
3504 /* no @ found */
3505 if (!iptr->nickptr || strpbrk(iptr->nuhmask, ".:"))
3506 strlcpy(iptr->hostptr, iptr->nuhmask, iptr->hostsize);
3507 else
3508 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3509 }
3510 }
3511 }
3512
3513 /*
3514 * flags_to_ascii
3515 *
3516 * inputs - flags is a bitmask
3517 * - pointer to table of ascii letters corresponding
3518 * to each bit
3519 * - flag 1 for convert ToLower if bit missing
3520 * 0 if ignore.
3521 * output - none
3522 * side effects - string pointed to by p has bitmap chars written to it
3523 */
3524 static void
3525 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3526 int lowerit)
3527 {
3528 unsigned int mask = 1;
3529 int i = 0;
3530
3531 for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3532 {
3533 if (flags & mask)
3534 *p++ = bit_table[i];
3535 else if (lowerit)
3536 *p++ = ToLower(bit_table[i]);
3537 }
3538 *p = '\0';
3539 }
3540
3541 /*
3542 * cidr_limit_reached
3543 *
3544 * inputs - int flag allowing over_rule of limits
3545 * - pointer to the ip to be added
3546 * - pointer to the class
3547 * output - non zero if limit reached
3548 * 0 if limit not reached
3549 * side effects -
3550 */
3551 static int
3552 cidr_limit_reached(int over_rule,
3553 struct irc_ssaddr *ip, struct ClassItem *aclass)
3554 {
3555 dlink_node *ptr = NULL;
3556 struct CidrItem *cidr;
3557
3558 if (aclass->number_per_cidr <= 0)
3559 return 0;
3560
3561 if (ip->ss.ss_family == AF_INET)
3562 {
3563 if (aclass->cidr_bitlen_ipv4 <= 0)
3564 return 0;
3565
3566 DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3567 {
3568 cidr = ptr->data;
3569 if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3570 {
3571 if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3572 return -1;
3573 cidr->number_on_this_cidr++;
3574 return 0;
3575 }
3576 }
3577 cidr = MyMalloc(sizeof(struct CidrItem));
3578 cidr->number_on_this_cidr = 1;
3579 cidr->mask = *ip;
3580 mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv4);
3581 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3582 }
3583 #ifdef IPV6
3584 else if (aclass->cidr_bitlen_ipv6 > 0)
3585 {
3586 DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3587 {
3588 cidr = ptr->data;
3589 if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3590 {
3591 if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3592 return -1;
3593 cidr->number_on_this_cidr++;
3594 return 0;
3595 }
3596 }
3597 cidr = MyMalloc(sizeof(struct CidrItem));
3598 cidr->number_on_this_cidr = 1;
3599 cidr->mask = *ip;
3600 mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv6);
3601 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3602 }
3603 #endif
3604 return 0;
3605 }
3606
3607 /*
3608 * remove_from_cidr_check
3609 *
3610 * inputs - pointer to the ip to be removed
3611 * - pointer to the class
3612 * output - NONE
3613 * side effects -
3614 */
3615 static void
3616 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3617 {
3618 dlink_node *ptr = NULL;
3619 dlink_node *next_ptr = NULL;
3620 struct CidrItem *cidr;
3621
3622 if (aclass->number_per_cidr == 0)
3623 return;
3624
3625 if (ip->ss.ss_family == AF_INET)
3626 {
3627 if (aclass->cidr_bitlen_ipv4 <= 0)
3628 return;
3629
3630 DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3631 {
3632 cidr = ptr->data;
3633 if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3634 {
3635 cidr->number_on_this_cidr--;
3636 if (cidr->number_on_this_cidr == 0)
3637 {
3638 dlinkDelete(ptr, &aclass->list_ipv4);
3639 MyFree(cidr);
3640 return;
3641 }
3642 }
3643 }
3644 }
3645 #ifdef IPV6
3646 else if (aclass->cidr_bitlen_ipv6 > 0)
3647 {
3648 DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3649 {
3650 cidr = ptr->data;
3651 if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3652 {
3653 cidr->number_on_this_cidr--;
3654 if (cidr->number_on_this_cidr == 0)
3655 {
3656 dlinkDelete(ptr, &aclass->list_ipv6);
3657 MyFree(cidr);
3658 return;
3659 }
3660 }
3661 }
3662 }
3663 #endif
3664 }
3665
3666 static void
3667 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3668 dlink_list *old_list, dlink_list *new_list, int changed)
3669 {
3670 dlink_node *ptr;
3671 struct Client *client_p;
3672 struct ConfItem *conf;
3673 struct AccessItem *aconf;
3674
3675 if (!changed)
3676 {
3677 *new_list = *old_list;
3678 old_list->head = old_list->tail = NULL;
3679 old_list->length = 0;
3680 return;
3681 }
3682
3683 DLINK_FOREACH(ptr, local_client_list.head)
3684 {
3685 client_p = ptr->data;
3686 if (client_p->localClient->aftype != aftype)
3687 continue;
3688 if (dlink_list_length(&client_p->localClient->confs) == 0)
3689 continue;
3690
3691 conf = client_p->localClient->confs.tail->data;
3692 if (conf->type == CLIENT_TYPE)
3693 {
3694 aconf = map_to_conf(conf);
3695 if (aconf->class_ptr == oldcl)
3696 cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3697 }
3698 }
3699 }
3700
3701 /*
3702 * rebuild_cidr_class
3703 *
3704 * inputs - pointer to old conf
3705 * - pointer to new_class
3706 * output - none
3707 * side effects - rebuilds the class link list of cidr blocks
3708 */
3709 void
3710 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3711 {
3712 struct ClassItem *old_class = map_to_conf(conf);
3713
3714 if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
3715 {
3716 if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
3717 rebuild_cidr_list(AF_INET, conf, new_class,
3718 &old_class->list_ipv4, &new_class->list_ipv4,
3719 old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
3720
3721 #ifdef IPV6
3722 if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
3723 rebuild_cidr_list(AF_INET6, conf, new_class,
3724 &old_class->list_ipv6, &new_class->list_ipv6,
3725 old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
3726 #endif
3727 }
3728
3729 destroy_cidr_class(old_class);
3730 }
3731
3732 /*
3733 * destroy_cidr_list
3734 *
3735 * inputs - pointer to class dlink list of cidr blocks
3736 * output - none
3737 * side effects - completely destroys the class link list of cidr blocks
3738 */
3739 static void
3740 destroy_cidr_list(dlink_list *list)
3741 {
3742 dlink_node *ptr = NULL, *next_ptr = NULL;
3743
3744 DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3745 {
3746 dlinkDelete(ptr, list);
3747 MyFree(ptr->data);
3748 }
3749 }
3750
3751 /*
3752 * destroy_cidr_class
3753 *
3754 * inputs - pointer to class
3755 * output - none
3756 * side effects - completely destroys the class link list of cidr blocks
3757 */
3758 static void
3759 destroy_cidr_class(struct ClassItem *aclass)
3760 {
3761 destroy_cidr_list(&aclass->list_ipv4);
3762 destroy_cidr_list(&aclass->list_ipv6);
3763 }

Properties

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