ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1005
Committed: Mon Aug 31 23:07:43 2009 UTC (14 years, 7 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 99440 byte(s)
Log Message:
- remove conf_add_d_conf wrapper

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

Properties

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