ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/s_conf.c
Revision: 32
Committed: Sun Oct 2 20:41:23 2005 UTC (18 years, 5 months ago) by knight
Content type: text/x-csrc
File size: 100366 byte(s)
Log Message:
- svn:keywords

File Contents

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

Properties

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