ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1366
Committed: Tue Apr 24 18:35:34 2012 UTC (11 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 98910 byte(s)
Log Message:
- Cleanup conf_add_server(). Remove traces of obsolete username verification
  for incoming server connections.

File Contents

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

Properties

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