ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1119
Committed: Fri Jan 7 22:01:47 2011 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.3/src/s_conf.c
File size: 99282 byte(s)
Log Message:
- removed HUB capability, which was a LL leftover

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 "list.h"
27 #include "ircd_defs.h"
28 #include "balloc.h"
29 #include "s_conf.h"
30 #include "s_serv.h"
31 #include "resv.h"
32 #include "channel.h"
33 #include "client.h"
34 #include "common.h"
35 #include "event.h"
36 #include "hash.h"
37 #include "hook.h"
38 #include "irc_string.h"
39 #include "sprintf_irc.h"
40 #include "s_bsd.h"
41 #include "irc_getaddrinfo.h"
42 #include "ircd.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 void *
141 map_to_conf(struct ConfItem *aconf)
142 {
143 void *conf;
144 conf = (void *)((uintptr_t)aconf +
145 (uintptr_t)sizeof(struct ConfItem));
146 return(conf);
147 }
148
149 struct ConfItem *
150 unmap_conf_item(void *aconf)
151 {
152 struct ConfItem *conf;
153
154 conf = (struct ConfItem *)((uintptr_t)aconf -
155 (uintptr_t)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 #ifdef HAVE_LIBPCRE
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 #endif
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 #ifdef HAVE_LIBCRYPTO
387 if (aconf->rsa_public_key)
388 RSA_free(aconf->rsa_public_key);
389 MyFree(aconf->rsa_public_key_file);
390 #endif
391
392 /* Yes, sigh. switch on type again */
393 switch(type)
394 {
395 case EXEMPTDLINE_TYPE:
396 case DLINE_TYPE:
397 case GLINE_TYPE:
398 case KLINE_TYPE:
399 case CLIENT_TYPE:
400 MyFree(conf);
401 break;
402
403 case OPER_TYPE:
404 aconf = map_to_conf(conf);
405 if (!IsConfIllegal(aconf))
406 dlinkDelete(&conf->node, &oconf_items);
407 MyFree(conf);
408 break;
409
410 case SERVER_TYPE:
411 aconf = map_to_conf(conf);
412 if (!IsConfIllegal(aconf))
413 dlinkDelete(&conf->node, &server_items);
414 MyFree(conf);
415 break;
416
417 default:
418 break;
419 }
420 break;
421
422 case HUB_TYPE:
423 match_item = map_to_conf(conf);
424 MyFree(match_item->user);
425 MyFree(match_item->host);
426 MyFree(match_item->reason);
427 MyFree(match_item->oper_reason);
428 /* If marked illegal, its already been pulled off of the hub_items list */
429 if (!match_item->illegal)
430 dlinkDelete(&conf->node, &hub_items);
431 MyFree(conf);
432 break;
433
434 case LEAF_TYPE:
435 match_item = map_to_conf(conf);
436 MyFree(match_item->user);
437 MyFree(match_item->host);
438 MyFree(match_item->reason);
439 MyFree(match_item->oper_reason);
440 /* If marked illegal, its already been pulled off of the leaf_items list */
441 if (!match_item->illegal)
442 dlinkDelete(&conf->node, &leaf_items);
443 MyFree(conf);
444 break;
445
446 case ULINE_TYPE:
447 match_item = map_to_conf(conf);
448 MyFree(match_item->user);
449 MyFree(match_item->host);
450 MyFree(match_item->reason);
451 MyFree(match_item->oper_reason);
452 dlinkDelete(&conf->node, &uconf_items);
453 MyFree(conf);
454 break;
455
456 case XLINE_TYPE:
457 match_item = map_to_conf(conf);
458 MyFree(match_item->user);
459 MyFree(match_item->host);
460 MyFree(match_item->reason);
461 MyFree(match_item->oper_reason);
462 dlinkDelete(&conf->node, &xconf_items);
463 MyFree(conf);
464 break;
465 #ifdef HAVE_LIBPCRE
466 case RKLINE_TYPE:
467 aconf = map_to_conf(conf);
468 MyFree(aconf->regexuser);
469 MyFree(aconf->regexhost);
470 MyFree(aconf->user);
471 MyFree(aconf->host);
472 MyFree(aconf->reason);
473 MyFree(aconf->oper_reason);
474 dlinkDelete(&conf->node, &rkconf_items);
475 MyFree(conf);
476 break;
477
478 case RXLINE_TYPE:
479 MyFree(conf->regexpname);
480 match_item = map_to_conf(conf);
481 MyFree(match_item->user);
482 MyFree(match_item->host);
483 MyFree(match_item->reason);
484 MyFree(match_item->oper_reason);
485 dlinkDelete(&conf->node, &rxconf_items);
486 MyFree(conf);
487 break;
488 #endif
489 case NRESV_TYPE:
490 match_item = map_to_conf(conf);
491 MyFree(match_item->user);
492 MyFree(match_item->host);
493 MyFree(match_item->reason);
494 MyFree(match_item->oper_reason);
495 dlinkDelete(&conf->node, &nresv_items);
496
497 if (conf->flags & CONF_FLAGS_TEMPORARY)
498 if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
499 free_dlink_node(m);
500
501 MyFree(conf);
502 break;
503
504 case GDENY_TYPE:
505 aconf = map_to_conf(conf);
506 MyFree(aconf->user);
507 MyFree(aconf->host);
508 dlinkDelete(&conf->node, &gdeny_items);
509 MyFree(conf);
510 break;
511
512 case CLUSTER_TYPE:
513 dlinkDelete(&conf->node, &cluster_items);
514 MyFree(conf);
515 break;
516
517 case CRESV_TYPE:
518 if (conf->flags & CONF_FLAGS_TEMPORARY)
519 if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
520 free_dlink_node(m);
521
522 MyFree(conf);
523 break;
524
525 case CLASS_TYPE:
526 dlinkDelete(&conf->node, &class_items);
527 MyFree(conf);
528 break;
529
530 default:
531 break;
532 }
533 }
534
535 /* free_access_item()
536 *
537 * inputs - pointer to conf to free
538 * output - none
539 * side effects - crucial password fields are zeroed, conf is freed
540 */
541 void
542 free_access_item(struct AccessItem *aconf)
543 {
544 struct ConfItem *conf;
545
546 if (aconf == NULL)
547 return;
548 conf = unmap_conf_item(aconf);
549 delete_conf_item(conf);
550 }
551
552 static const unsigned int shared_bit_table[] =
553 { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
554
555 /* report_confitem_types()
556 *
557 * inputs - pointer to client requesting confitem report
558 * - ConfType to report
559 * output - none
560 * side effects -
561 */
562 void
563 report_confitem_types(struct Client *source_p, ConfType type, int temp)
564 {
565 dlink_node *ptr = NULL;
566 struct ConfItem *conf = NULL;
567 struct AccessItem *aconf = NULL;
568 struct MatchItem *matchitem = NULL;
569 struct ClassItem *classitem = NULL;
570 char buf[12];
571 char *p = NULL;
572 const char *pfx = NULL;
573
574 switch (type)
575 {
576 case GDENY_TYPE:
577 DLINK_FOREACH(ptr, gdeny_items.head)
578 {
579 conf = ptr->data;
580 aconf = map_to_conf(conf);
581
582 p = buf;
583
584 if (aconf->flags & GDENY_BLOCK)
585 *p++ = 'B';
586 else
587 *p++ = 'b';
588
589 if (aconf->flags & GDENY_REJECT)
590 *p++ = 'R';
591 else
592 *p++ = 'r';
593
594 *p = '\0';
595
596 sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
597 me.name, RPL_STATSDEBUG, source_p->name,
598 aconf->user, aconf->host, conf->name, buf);
599 }
600 break;
601
602 case XLINE_TYPE:
603 DLINK_FOREACH(ptr, xconf_items.head)
604 {
605 conf = ptr->data;
606 matchitem = map_to_conf(conf);
607
608 sendto_one(source_p, form_str(RPL_STATSXLINE),
609 me.name, source_p->name,
610 matchitem->hold ? "x": "X", matchitem->count,
611 conf->name, matchitem->reason);
612 }
613 break;
614
615 #ifdef HAVE_LIBPCRE
616 case RXLINE_TYPE:
617 DLINK_FOREACH(ptr, rxconf_items.head)
618 {
619 conf = ptr->data;
620 matchitem = map_to_conf(conf);
621
622 sendto_one(source_p, form_str(RPL_STATSXLINE),
623 me.name, source_p->name,
624 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 #endif
645
646 case ULINE_TYPE:
647 DLINK_FOREACH(ptr, uconf_items.head)
648 {
649 conf = ptr->data;
650 matchitem = map_to_conf(conf);
651
652 p = buf;
653
654 /* some of these are redundant for the sake of
655 * consistency with cluster{} flags
656 */
657 *p++ = 'c';
658 flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
659
660 sendto_one(source_p, form_str(RPL_STATSULINE),
661 me.name, source_p->name, conf->name,
662 matchitem->user?matchitem->user: "*",
663 matchitem->host?matchitem->host: "*", buf);
664 }
665
666 DLINK_FOREACH(ptr, cluster_items.head)
667 {
668 conf = ptr->data;
669
670 p = buf;
671
672 *p++ = 'C';
673 flags_to_ascii(conf->flags, shared_bit_table, p, 0);
674
675 sendto_one(source_p, form_str(RPL_STATSULINE),
676 me.name, source_p->name, conf->name,
677 "*", "*", buf);
678 }
679
680 break;
681
682 case OPER_TYPE:
683 DLINK_FOREACH(ptr, oconf_items.head)
684 {
685 conf = ptr->data;
686 aconf = map_to_conf(conf);
687
688 /* Don't allow non opers to see oper privs */
689 if (IsOper(source_p))
690 sendto_one(source_p, form_str(RPL_STATSOLINE),
691 me.name, source_p->name, 'O', aconf->user, aconf->host,
692 conf->name, oper_privs_as_string(aconf->port),
693 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
694 else
695 sendto_one(source_p, form_str(RPL_STATSOLINE),
696 me.name, source_p->name, 'O', aconf->user, aconf->host,
697 conf->name, "0",
698 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
699 }
700 break;
701
702 case CLASS_TYPE:
703 DLINK_FOREACH(ptr, class_items.head)
704 {
705 conf = ptr->data;
706 classitem = map_to_conf(conf);
707 sendto_one(source_p, form_str(RPL_STATSYLINE),
708 me.name, source_p->name, 'Y',
709 conf->name, PingFreq(classitem),
710 ConFreq(classitem),
711 MaxTotal(classitem), MaxSendq(classitem),
712 CurrUserCount(classitem),
713 classitem->active ? "active" : "disabled");
714 }
715 break;
716
717 case CONF_TYPE:
718 case CLIENT_TYPE:
719 break;
720
721 case SERVER_TYPE:
722 DLINK_FOREACH(ptr, server_items.head)
723 {
724 p = buf;
725
726 conf = ptr->data;
727 aconf = map_to_conf(conf);
728
729 buf[0] = '\0';
730
731 if (IsConfAllowAutoConn(aconf))
732 *p++ = 'A';
733 if (IsConfCryptLink(aconf))
734 *p++ = 'C';
735 if (IsConfTopicBurst(aconf))
736 *p++ = 'T';
737 if (IsConfCompressed(aconf))
738 *p++ = 'Z';
739 if (buf[0] == '\0')
740 *p++ = '*';
741
742 *p = '\0';
743
744 /*
745 * Allow admins to see actual ips unless hide_server_ips is enabled
746 */
747 if (!ConfigServerHide.hide_server_ips && IsAdmin(source_p))
748 sendto_one(source_p, form_str(RPL_STATSCLINE),
749 me.name, source_p->name, 'C', aconf->host,
750 buf, conf->name, aconf->port,
751 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
752 else
753 sendto_one(source_p, form_str(RPL_STATSCLINE),
754 me.name, source_p->name, 'C',
755 "*@127.0.0.1", buf, conf->name, aconf->port,
756 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
757 }
758 break;
759
760 case HUB_TYPE:
761 DLINK_FOREACH(ptr, hub_items.head)
762 {
763 conf = ptr->data;
764 matchitem = map_to_conf(conf);
765 sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
766 source_p->name, 'H', matchitem->host, conf->name, 0, "*");
767 }
768 break;
769
770 case LEAF_TYPE:
771 DLINK_FOREACH(ptr, leaf_items.head)
772 {
773 conf = ptr->data;
774 matchitem = map_to_conf(conf);
775 sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
776 source_p->name, 'L', matchitem->host, conf->name, 0, "*");
777 }
778 break;
779
780 case GLINE_TYPE:
781 case KLINE_TYPE:
782 case DLINE_TYPE:
783 case EXEMPTDLINE_TYPE:
784 case CRESV_TYPE:
785 case NRESV_TYPE:
786 case CLUSTER_TYPE:
787 default:
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 uint32_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 uint32_t *ip = (uint32_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 #ifdef HAVE_LIBPCRE
1576 case RXLINE_TYPE:
1577 DLINK_FOREACH(ptr, list_p->head)
1578 {
1579 conf = ptr->data;
1580 assert(conf->regexpname);
1581
1582 if (!ircd_pcre_exec(conf->regexpname, name))
1583 return conf;
1584 }
1585 break;
1586 #endif
1587 case XLINE_TYPE:
1588 case ULINE_TYPE:
1589 case NRESV_TYPE:
1590 DLINK_FOREACH(ptr, list_p->head)
1591 {
1592 conf = ptr->data;
1593
1594 match_item = map_to_conf(conf);
1595 if (EmptyString(conf->name))
1596 continue;
1597 if ((name != NULL) && match_esc(conf->name, name))
1598 {
1599 if ((user == NULL && (host == NULL)))
1600 return conf;
1601 if ((match_item->action & action) != action)
1602 continue;
1603 if (EmptyString(match_item->user) || EmptyString(match_item->host))
1604 return conf;
1605 if (match(match_item->user, user) && match(match_item->host, host))
1606 return conf;
1607 }
1608 }
1609 break;
1610
1611 case SERVER_TYPE:
1612 DLINK_FOREACH(ptr, list_p->head)
1613 {
1614 conf = ptr->data;
1615 aconf = map_to_conf(conf);
1616
1617 if ((name != NULL) && match_esc(name, conf->name))
1618 return conf;
1619 else if ((host != NULL) && match_esc(host, aconf->host))
1620 return conf;
1621 }
1622 break;
1623
1624 default:
1625 break;
1626 }
1627 return NULL;
1628 }
1629
1630 /* find_exact_name_conf()
1631 *
1632 * inputs - type of link list to look in
1633 * - pointer to name string to find
1634 * - pointer to user
1635 * - pointer to host
1636 * output - NULL or pointer to found struct MatchItem
1637 * side effects - looks for an exact match on name field
1638 */
1639 struct ConfItem *
1640 find_exact_name_conf(ConfType type, const char *name,
1641 const char *user, const char *host)
1642 {
1643 dlink_node *ptr = NULL;
1644 struct AccessItem *aconf;
1645 struct ConfItem *conf;
1646 struct MatchItem *match_item;
1647 dlink_list *list_p;
1648
1649 list_p = map_to_list(type);
1650
1651 switch(type)
1652 {
1653 case RXLINE_TYPE:
1654 case XLINE_TYPE:
1655 case ULINE_TYPE:
1656 case NRESV_TYPE:
1657
1658 DLINK_FOREACH(ptr, list_p->head)
1659 {
1660 conf = ptr->data;
1661 match_item = (struct MatchItem *)map_to_conf(conf);
1662 if (EmptyString(conf->name))
1663 continue;
1664
1665 if (irccmp(conf->name, name) == 0)
1666 {
1667 if ((user == NULL && (host == NULL)))
1668 return (conf);
1669 if (EmptyString(match_item->user) || EmptyString(match_item->host))
1670 return (conf);
1671 if (match(match_item->user, user) && match(match_item->host, host))
1672 return (conf);
1673 }
1674 }
1675 break;
1676
1677 case OPER_TYPE:
1678 DLINK_FOREACH(ptr, list_p->head)
1679 {
1680 conf = ptr->data;
1681 aconf = (struct AccessItem *)map_to_conf(conf);
1682 if (EmptyString(conf->name))
1683 continue;
1684
1685 if (irccmp(conf->name, name) == 0)
1686 {
1687 if ((user == NULL && (host == NULL)))
1688 return (conf);
1689 if (EmptyString(aconf->user) || EmptyString(aconf->host))
1690 return (conf);
1691 if (match(aconf->user, user) && match(aconf->host, host))
1692 return (conf);
1693 }
1694 }
1695 break;
1696
1697 case SERVER_TYPE:
1698 DLINK_FOREACH(ptr, list_p->head)
1699 {
1700 conf = ptr->data;
1701 aconf = (struct AccessItem *)map_to_conf(conf);
1702 if (EmptyString(conf->name))
1703 continue;
1704
1705 if (name == NULL)
1706 {
1707 if (EmptyString(aconf->host))
1708 continue;
1709 if (irccmp(aconf->host, host) == 0)
1710 return(conf);
1711 }
1712 else if (irccmp(conf->name, name) == 0)
1713 {
1714 return (conf);
1715 }
1716 }
1717 break;
1718
1719 case CLASS_TYPE:
1720 DLINK_FOREACH(ptr, list_p->head)
1721 {
1722 conf = ptr->data;
1723 if (EmptyString(conf->name))
1724 continue;
1725
1726 if (irccmp(conf->name, name) == 0)
1727 return (conf);
1728 }
1729 break;
1730
1731 default:
1732 break;
1733 }
1734 return(NULL);
1735 }
1736
1737 /* rehash()
1738 *
1739 * Actual REHASH service routine. Called with sig == 0 if it has been called
1740 * as a result of an operator issuing this command, else assume it has been
1741 * called as a result of the server receiving a HUP signal.
1742 */
1743 int
1744 rehash(int sig)
1745 {
1746 if (sig != 0)
1747 sendto_realops_flags(UMODE_ALL, L_ALL,
1748 "Got signal SIGHUP, reloading ircd.conf file");
1749
1750 restart_resolver();
1751
1752 /* don't close listeners until we know we can go ahead with the rehash */
1753
1754 /* Check to see if we magically got(or lost) IPv6 support */
1755 check_can_use_v6();
1756
1757 read_conf_files(0);
1758
1759 if (ServerInfo.description != NULL)
1760 strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1761
1762 #ifndef STATIC_MODULES
1763 load_conf_modules();
1764 #endif
1765
1766 flush_deleted_I_P();
1767
1768 rehashed_klines = 1;
1769
1770 if (ConfigLoggingEntry.use_logging)
1771 reopen_log(logFileName);
1772
1773 return(0);
1774 }
1775
1776 /* set_default_conf()
1777 *
1778 * inputs - NONE
1779 * output - NONE
1780 * side effects - Set default values here.
1781 * This is called **PRIOR** to parsing the
1782 * configuration file. If you want to do some validation
1783 * of values later, put them in validate_conf().
1784 */
1785 static void
1786 set_default_conf(void)
1787 {
1788 /* verify init_class() ran, this should be an unnecessary check
1789 * but its not much work.
1790 */
1791 assert(class_default == (struct ConfItem *) class_items.tail->data);
1792
1793 #ifdef HAVE_LIBCRYPTO
1794 ServerInfo.rsa_private_key = NULL;
1795 ServerInfo.rsa_private_key_file = NULL;
1796 #endif
1797
1798 /* ServerInfo.name is not rehashable */
1799 /* ServerInfo.name = ServerInfo.name; */
1800 ServerInfo.description = NULL;
1801 DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1802 DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1803
1804 memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1805 ServerInfo.specific_ipv4_vhost = 0;
1806 memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
1807 ServerInfo.specific_ipv6_vhost = 0;
1808
1809 ServerInfo.max_clients = MAXCLIENTS_MAX;
1810
1811 ServerInfo.hub = 0;
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;
1868 ConfigFileEntry.failed_oper_notice = YES;
1869 ConfigFileEntry.dots_in_ident = 0;
1870 ConfigFileEntry.min_nonwildcard = 4;
1871 ConfigFileEntry.min_nonwildcard_simple = 3;
1872 ConfigFileEntry.max_accept = 20;
1873 ConfigFileEntry.anti_nick_flood = NO;
1874 ConfigFileEntry.max_nick_time = 20;
1875 ConfigFileEntry.max_nick_changes = 5;
1876 ConfigFileEntry.anti_spam_exit_message_time = 0;
1877 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1878 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1879 ConfigFileEntry.kline_with_reason = YES;
1880 ConfigFileEntry.kline_reason = NULL;
1881 ConfigFileEntry.warn_no_nline = YES;
1882 ConfigFileEntry.stats_o_oper_only = NO;
1883 ConfigFileEntry.stats_k_oper_only = 1; /* masked */
1884 ConfigFileEntry.stats_i_oper_only = 1; /* masked */
1885 ConfigFileEntry.stats_P_oper_only = NO;
1886 ConfigFileEntry.caller_id_wait = 60;
1887 ConfigFileEntry.opers_bypass_callerid = NO;
1888 ConfigFileEntry.pace_wait = 10;
1889 ConfigFileEntry.pace_wait_simple = 1;
1890 ConfigFileEntry.short_motd = NO;
1891 ConfigFileEntry.ping_cookie = NO;
1892 ConfigFileEntry.no_oper_flood = NO;
1893 ConfigFileEntry.true_no_oper_flood = NO;
1894 ConfigFileEntry.oper_pass_resv = YES;
1895 ConfigFileEntry.glines = NO;
1896 ConfigFileEntry.gline_time = 12 * 3600;
1897 ConfigFileEntry.idletime = 0;
1898 ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1899 ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1900 ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1901 ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1902 UMODE_OPERWALL | UMODE_WALLOP;
1903 DupString(ConfigFileEntry.servlink_path, SLPATH);
1904 #ifdef HAVE_LIBCRYPTO
1905 /* jdc -- This is our default value for a cipher. According to the
1906 * CRYPTLINK document (doc/cryptlink.txt), BF/128 must be supported
1907 * under all circumstances if cryptlinks are enabled. So,
1908 * this will be our default.
1909 *
1910 * NOTE: I apologise for the hard-coded value of "1" (BF/128).
1911 * This should be moved into a find_cipher() routine.
1912 */
1913 ConfigFileEntry.default_cipher_preference = &CipherTable[1];
1914 #endif
1915 ConfigFileEntry.use_egd = NO;
1916 ConfigFileEntry.egdpool_path = NULL;
1917 #ifdef HAVE_LIBZ
1918 ConfigFileEntry.compression_level = 0;
1919 #endif
1920 ConfigFileEntry.throttle_time = 10;
1921 }
1922
1923 /* read_conf()
1924 *
1925 * inputs - file descriptor pointing to config file to use
1926 * output - None
1927 * side effects - Read configuration file.
1928 */
1929 static void
1930 read_conf(FBFILE *file)
1931 {
1932 lineno = 0;
1933
1934 set_default_conf(); /* Set default values prior to conf parsing */
1935 conf_parser_ctx.pass = 1;
1936 yyparse(); /* pick up the classes first */
1937
1938 fbrewind(file);
1939
1940 conf_parser_ctx.pass = 2;
1941 yyparse(); /* Load the values from the conf */
1942 validate_conf(); /* Check to make sure some values are still okay. */
1943 /* Some global values are also loaded here. */
1944 check_class(); /* Make sure classes are valid */
1945 }
1946
1947 static void
1948 validate_conf(void)
1949 {
1950 if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1951 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1952
1953 if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1954 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1955
1956 if (ConfigFileEntry.servlink_path == NULL)
1957 DupString(ConfigFileEntry.servlink_path, SLPATH);
1958
1959 if (ServerInfo.network_name == NULL)
1960 DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1961
1962 if (ServerInfo.network_desc == NULL)
1963 DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1964
1965 if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1966 (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1967 ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1968
1969 ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1970 }
1971
1972 /* lookup_confhost()
1973 *
1974 * start DNS lookups of all hostnames in the conf
1975 * line and convert an IP addresses in a.b.c.d number for to IP#s.
1976 */
1977 static void
1978 lookup_confhost(struct ConfItem *conf)
1979 {
1980 struct AccessItem *aconf;
1981 struct addrinfo hints, *res;
1982
1983 aconf = map_to_conf(conf);
1984
1985 if (EmptyString(aconf->host) ||
1986 EmptyString(aconf->user))
1987 {
1988 ilog(L_ERROR, "Host/server name error: (%s) (%s)",
1989 aconf->host, conf->name);
1990 return;
1991 }
1992
1993 if (strchr(aconf->host, '*') ||
1994 strchr(aconf->host, '?'))
1995 return;
1996
1997 /* Do name lookup now on hostnames given and store the
1998 * ip numbers in conf structure.
1999 */
2000 memset(&hints, 0, sizeof(hints));
2001
2002 hints.ai_family = AF_UNSPEC;
2003 hints.ai_socktype = SOCK_STREAM;
2004
2005 /* Get us ready for a bind() and don't bother doing dns lookup */
2006 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
2007
2008 if (irc_getaddrinfo(aconf->host, NULL, &hints, &res))
2009 {
2010 conf_dns_lookup(aconf);
2011 return;
2012 }
2013
2014 assert(res != NULL);
2015
2016 memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
2017 aconf->ipnum.ss_len = res->ai_addrlen;
2018 aconf->ipnum.ss.ss_family = res->ai_family;
2019 irc_freeaddrinfo(res);
2020 }
2021
2022 /* conf_connect_allowed()
2023 *
2024 * inputs - pointer to inaddr
2025 * - int type ipv4 or ipv6
2026 * output - BANNED or accepted
2027 * side effects - none
2028 */
2029 int
2030 conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
2031 {
2032 struct ip_entry *ip_found;
2033 struct AccessItem *aconf = find_dline_conf(addr, aftype);
2034
2035 /* DLINE exempt also gets you out of static limits/pacing... */
2036 if (aconf && (aconf->status & CONF_EXEMPTDLINE))
2037 return 0;
2038
2039 if (aconf != NULL)
2040 return BANNED_CLIENT;
2041
2042 ip_found = find_or_add_ip(addr);
2043
2044 if ((CurrentTime - ip_found->last_attempt) <
2045 ConfigFileEntry.throttle_time)
2046 {
2047 ip_found->last_attempt = CurrentTime;
2048 return TOO_FAST;
2049 }
2050
2051 ip_found->last_attempt = CurrentTime;
2052 return 0;
2053 }
2054
2055 static struct AccessItem *
2056 find_regexp_kline(const char *uhi[])
2057 {
2058 #ifdef HAVE_LIBPCRE
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 #endif
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 #ifdef HAVE_LIBPCRE
2475 parse_conf_file(RKLINE_TYPE, cold);
2476 parse_conf_file(RXLINE_TYPE, cold);
2477 #endif
2478 parse_conf_file(KLINE_TYPE, cold);
2479 parse_conf_file(DLINE_TYPE, cold);
2480 parse_conf_file(XLINE_TYPE, cold);
2481 parse_conf_file(NRESV_TYPE, cold);
2482 parse_conf_file(CRESV_TYPE, cold);
2483 }
2484
2485 /* parse_conf_file()
2486 *
2487 * inputs - type of conf file to parse
2488 * output - none
2489 * side effects - conf file for givenconf type is opened and read then parsed
2490 */
2491 static void
2492 parse_conf_file(int type, int cold)
2493 {
2494 FBFILE *file = NULL;
2495 const char *filename = get_conf_name(type);
2496
2497 if ((file = fbopen(filename, "r")) == NULL)
2498 {
2499 if (cold)
2500 ilog(L_ERROR, "Unable to read configuration file '%s': %s",
2501 filename, strerror(errno));
2502 else
2503 sendto_realops_flags(UMODE_ALL, L_ALL,
2504 "Unable to read configuration file '%s': %s",
2505 filename, strerror(errno));
2506 }
2507 else
2508 {
2509 parse_csv_file(file, type);
2510 fbclose(file);
2511 }
2512 }
2513
2514 /* clear_out_old_conf()
2515 *
2516 * inputs - none
2517 * output - none
2518 * side effects - Clear out the old configuration
2519 */
2520 static void
2521 clear_out_old_conf(void)
2522 {
2523 dlink_node *ptr = NULL, *next_ptr = NULL;
2524 struct ConfItem *conf;
2525 struct AccessItem *aconf;
2526 struct ClassItem *cltmp;
2527 struct MatchItem *match_item;
2528 dlink_list *free_items [] = {
2529 &server_items, &oconf_items, &hub_items, &leaf_items,
2530 &uconf_items, &xconf_items, &rxconf_items, &rkconf_items,
2531 &nresv_items, &cluster_items, &gdeny_items, NULL
2532 };
2533
2534 dlink_list ** iterator = free_items; /* C is dumb */
2535
2536 /* We only need to free anything allocated by yyparse() here.
2537 * Resetting structs, etc, is taken care of by set_default_conf().
2538 */
2539
2540 for (; *iterator != NULL; iterator++)
2541 {
2542 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2543 {
2544 conf = ptr->data;
2545 /* XXX This is less than pretty */
2546 if (conf->type == SERVER_TYPE)
2547 {
2548 aconf = map_to_conf(conf);
2549
2550 if (aconf->clients != 0)
2551 {
2552 SetConfIllegal(aconf);
2553 dlinkDelete(&conf->node, &server_items);
2554 }
2555 else
2556 {
2557 delete_conf_item(conf);
2558 }
2559 }
2560 else if (conf->type == OPER_TYPE)
2561 {
2562 aconf = map_to_conf(conf);
2563
2564 if (aconf->clients != 0)
2565 {
2566 SetConfIllegal(aconf);
2567 dlinkDelete(&conf->node, &oconf_items);
2568 }
2569 else
2570 {
2571 delete_conf_item(conf);
2572 }
2573 }
2574 else if (conf->type == CLIENT_TYPE)
2575 {
2576 aconf = map_to_conf(conf);
2577
2578 if (aconf->clients != 0)
2579 {
2580 SetConfIllegal(aconf);
2581 }
2582 else
2583 {
2584 delete_conf_item(conf);
2585 }
2586 }
2587 else if (conf->type == XLINE_TYPE ||
2588 conf->type == RXLINE_TYPE ||
2589 conf->type == RKLINE_TYPE)
2590 {
2591 /* temporary (r)xlines are also on
2592 * the (r)xconf items list */
2593 if (conf->flags & CONF_FLAGS_TEMPORARY)
2594 continue;
2595
2596 delete_conf_item(conf);
2597 }
2598 else
2599 {
2600 if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2601 {
2602 match_item = map_to_conf(conf);
2603 if (match_item->ref_count <= 0)
2604 delete_conf_item(conf);
2605 else
2606 {
2607 match_item->illegal = 1;
2608 dlinkDelete(&conf->node, *iterator);
2609 }
2610 }
2611 else
2612 delete_conf_item(conf);
2613 }
2614 }
2615 }
2616
2617 /*
2618 * don't delete the class table, rather mark all entries
2619 * for deletion. The table is cleaned up by check_class. - avalon
2620 */
2621 DLINK_FOREACH(ptr, class_items.head)
2622 {
2623 cltmp = map_to_conf(ptr->data);
2624
2625 if (ptr != class_items.tail) /* never mark the "default" class */
2626 cltmp->active = 0;
2627 }
2628
2629 clear_out_address_conf();
2630
2631 /* clean out module paths */
2632 #ifndef STATIC_MODULES
2633 mod_clear_paths();
2634 #endif
2635
2636 /* clean out ServerInfo */
2637 MyFree(ServerInfo.description);
2638 ServerInfo.description = NULL;
2639 MyFree(ServerInfo.network_name);
2640 ServerInfo.network_name = NULL;
2641 MyFree(ServerInfo.network_desc);
2642 ServerInfo.network_desc = NULL;
2643 MyFree(ConfigFileEntry.egdpool_path);
2644 ConfigFileEntry.egdpool_path = NULL;
2645 #ifdef HAVE_LIBCRYPTO
2646 if (ServerInfo.rsa_private_key != NULL)
2647 {
2648 RSA_free(ServerInfo.rsa_private_key);
2649 ServerInfo.rsa_private_key = NULL;
2650 }
2651
2652 MyFree(ServerInfo.rsa_private_key_file);
2653 ServerInfo.rsa_private_key_file = NULL;
2654 #endif
2655
2656 /* clean out old resvs from the conf */
2657 clear_conf_resv();
2658
2659 /* clean out AdminInfo */
2660 MyFree(AdminInfo.name);
2661 AdminInfo.name = NULL;
2662 MyFree(AdminInfo.email);
2663 AdminInfo.email = NULL;
2664 MyFree(AdminInfo.description);
2665 AdminInfo.description = NULL;
2666
2667 /* operator{} and class{} blocks are freed above */
2668 /* clean out listeners */
2669 close_listeners();
2670
2671 /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2672 * exempt{} and gecos{} blocks are freed above too
2673 */
2674
2675 /* clean out general */
2676 MyFree(ConfigFileEntry.servlink_path);
2677 ConfigFileEntry.servlink_path = NULL;
2678 #ifdef HAVE_LIBCRYPTO
2679 ConfigFileEntry.default_cipher_preference = NULL;
2680 #endif /* HAVE_LIBCRYPTO */
2681 delete_isupport("INVEX");
2682 delete_isupport("EXCEPTS");
2683 }
2684
2685 /* flush_deleted_I_P()
2686 *
2687 * inputs - none
2688 * output - none
2689 * side effects - This function removes I/P conf items
2690 */
2691 static void
2692 flush_deleted_I_P(void)
2693 {
2694 dlink_node *ptr;
2695 dlink_node *next_ptr;
2696 struct ConfItem *conf;
2697 struct AccessItem *aconf;
2698 dlink_list * free_items [] = {
2699 &server_items, &oconf_items, NULL
2700 };
2701 dlink_list ** iterator = free_items; /* C is dumb */
2702
2703 /* flush out deleted I and P lines
2704 * although still in use.
2705 */
2706 for (; *iterator != NULL; iterator++)
2707 {
2708 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2709 {
2710 conf = ptr->data;
2711 aconf = (struct AccessItem *)map_to_conf(conf);
2712
2713 if (IsConfIllegal(aconf))
2714 {
2715 dlinkDelete(ptr, *iterator);
2716
2717 if (aconf->clients == 0)
2718 delete_conf_item(conf);
2719 }
2720 }
2721 }
2722 }
2723
2724 /* get_conf_name()
2725 *
2726 * inputs - type of conf file to return name of file for
2727 * output - pointer to filename for type of conf
2728 * side effects - none
2729 */
2730 const char *
2731 get_conf_name(ConfType type)
2732 {
2733 switch (type)
2734 {
2735 case CONF_TYPE:
2736 return ConfigFileEntry.configfile;
2737 break;
2738 case KLINE_TYPE:
2739 return ConfigFileEntry.klinefile;
2740 break;
2741 case RKLINE_TYPE:
2742 return ConfigFileEntry.rklinefile;
2743 break;
2744 case DLINE_TYPE:
2745 return ConfigFileEntry.dlinefile;
2746 break;
2747 case XLINE_TYPE:
2748 return ConfigFileEntry.xlinefile;
2749 break;
2750 case RXLINE_TYPE:
2751 return ConfigFileEntry.rxlinefile;
2752 break;
2753 case CRESV_TYPE:
2754 return ConfigFileEntry.cresvfile;
2755 break;
2756 case NRESV_TYPE:
2757 return ConfigFileEntry.nresvfile;
2758 break;
2759 case GLINE_TYPE:
2760 return ConfigFileEntry.glinefile;
2761 break;
2762
2763 default:
2764 return NULL; /* This should NEVER HAPPEN since we call this function
2765 only with the above values, this will cause us to core
2766 at some point if this happens so we know where it was */
2767 }
2768 }
2769
2770 #define BAD_PING (-1)
2771
2772 /* get_conf_ping()
2773 *
2774 * inputs - pointer to struct AccessItem
2775 * - pointer to a variable that receives ping warning time
2776 * output - ping frequency
2777 * side effects - NONE
2778 */
2779 static int
2780 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2781 {
2782 struct ClassItem *aclass;
2783 struct AccessItem *aconf;
2784
2785 if (conf != NULL)
2786 {
2787 aconf = (struct AccessItem *)map_to_conf(conf);
2788 if (aconf->class_ptr != NULL)
2789 {
2790 aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2791 *pingwarn = PingWarning(aclass);
2792 return PingFreq(aclass);
2793 }
2794 }
2795
2796 return BAD_PING;
2797 }
2798
2799 /* get_client_class()
2800 *
2801 * inputs - pointer to client struct
2802 * output - pointer to name of class
2803 * side effects - NONE
2804 */
2805 const char *
2806 get_client_class(struct Client *target_p)
2807 {
2808 dlink_node *ptr;
2809 struct ConfItem *conf;
2810 struct AccessItem *aconf;
2811
2812 if (target_p != NULL && !IsMe(target_p) &&
2813 target_p->localClient->confs.head != NULL)
2814 {
2815 DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2816 {
2817 conf = ptr->data;
2818
2819 if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2820 conf->type == OPER_TYPE)
2821 {
2822 aconf = (struct AccessItem *) map_to_conf(conf);
2823 if (aconf->class_ptr != NULL)
2824 return aconf->class_ptr->name;
2825 }
2826 }
2827 }
2828
2829 return "default";
2830 }
2831
2832 /* get_client_ping()
2833 *
2834 * inputs - pointer to client struct
2835 * - pointer to a variable that receives ping warning time
2836 * output - ping frequency
2837 * side effects - NONE
2838 */
2839 int
2840 get_client_ping(struct Client *target_p, int *pingwarn)
2841 {
2842 int ping;
2843 struct ConfItem *conf;
2844 dlink_node *nlink;
2845
2846 if (target_p->localClient->confs.head != NULL)
2847 DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2848 {
2849 conf = nlink->data;
2850
2851 if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2852 (conf->type == OPER_TYPE))
2853 {
2854 ping = get_conf_ping(conf, pingwarn);
2855 if (ping > 0)
2856 return ping;
2857 }
2858 }
2859
2860 *pingwarn = 0;
2861 return DEFAULT_PINGFREQUENCY;
2862 }
2863
2864 /* find_class()
2865 *
2866 * inputs - string name of class
2867 * output - corresponding Class pointer
2868 * side effects - NONE
2869 */
2870 struct ConfItem *
2871 find_class(const char *classname)
2872 {
2873 struct ConfItem *conf;
2874
2875 if ((conf = find_exact_name_conf(CLASS_TYPE, classname, NULL, NULL)) != NULL)
2876 return conf;
2877
2878 return class_default;
2879 }
2880
2881 /* check_class()
2882 *
2883 * inputs - NONE
2884 * output - NONE
2885 * side effects -
2886 */
2887 void
2888 check_class(void)
2889 {
2890 dlink_node *ptr = NULL, *next_ptr = NULL;
2891
2892 DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2893 {
2894 struct ClassItem *aclass = map_to_conf(ptr->data);
2895
2896 if (!aclass->active && !CurrUserCount(aclass))
2897 {
2898 destroy_cidr_class(aclass);
2899 delete_conf_item(ptr->data);
2900 }
2901 }
2902 }
2903
2904 /* init_class()
2905 *
2906 * inputs - NONE
2907 * output - NONE
2908 * side effects -
2909 */
2910 void
2911 init_class(void)
2912 {
2913 struct ClassItem *aclass;
2914
2915 class_default = make_conf_item(CLASS_TYPE);
2916
2917 aclass = map_to_conf(class_default);
2918 aclass->active = 1;
2919 DupString(class_default->name, "default");
2920 ConFreq(aclass) = DEFAULT_CONNECTFREQUENCY;
2921 PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
2922 MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
2923 MaxSendq(aclass) = DEFAULT_SENDQ;
2924
2925 client_check_cb = register_callback("check_client", check_client);
2926 }
2927
2928 /* get_sendq()
2929 *
2930 * inputs - pointer to client
2931 * output - sendq for this client as found from its class
2932 * side effects - NONE
2933 */
2934 unsigned int
2935 get_sendq(struct Client *client_p)
2936 {
2937 unsigned int sendq = DEFAULT_SENDQ;
2938 dlink_node *ptr;
2939 struct ConfItem *conf;
2940 struct ConfItem *class_conf;
2941 struct ClassItem *aclass;
2942 struct AccessItem *aconf;
2943
2944 if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2945 {
2946 DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2947 {
2948 conf = ptr->data;
2949 if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2950 || (conf->type == CLIENT_TYPE))
2951 {
2952 aconf = (struct AccessItem *)map_to_conf(conf);
2953 if ((class_conf = aconf->class_ptr) == NULL)
2954 continue;
2955 aclass = (struct ClassItem *)map_to_conf(class_conf);
2956 sendq = MaxSendq(aclass);
2957 return sendq;
2958 }
2959 }
2960 }
2961 /* XXX return a default?
2962 * if here, then there wasn't an attached conf with a sendq
2963 * that is very bad -Dianora
2964 */
2965 return DEFAULT_SENDQ;
2966 }
2967
2968 /* conf_add_class_to_conf()
2969 *
2970 * inputs - pointer to config item
2971 * output - NONE
2972 * side effects - Add a class pointer to a conf
2973 */
2974 void
2975 conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
2976 {
2977 struct AccessItem *aconf = map_to_conf(conf);
2978 struct ClassItem *class = NULL;
2979
2980 if (class_name == NULL)
2981 {
2982 aconf->class_ptr = class_default;
2983
2984 if (conf->type == CLIENT_TYPE)
2985 sendto_realops_flags(UMODE_ALL, L_ALL,
2986 "Warning *** Defaulting to default class for %s@%s",
2987 aconf->user, aconf->host);
2988 else
2989 sendto_realops_flags(UMODE_ALL, L_ALL,
2990 "Warning *** Defaulting to default class for %s",
2991 conf->name);
2992 }
2993 else
2994 aconf->class_ptr = find_class(class_name);
2995
2996 if (aconf->class_ptr)
2997 class = map_to_conf(aconf->class_ptr);
2998
2999 if (aconf->class_ptr == NULL || !class->active)
3000 {
3001 if (conf->type == CLIENT_TYPE)
3002 sendto_realops_flags(UMODE_ALL, L_ALL,
3003 "Warning *** Defaulting to default class for %s@%s",
3004 aconf->user, aconf->host);
3005 else
3006 sendto_realops_flags(UMODE_ALL, L_ALL,
3007 "Warning *** Defaulting to default class for %s",
3008 conf->name);
3009 aconf->class_ptr = class_default;
3010 }
3011 }
3012
3013 /* conf_add_server()
3014 *
3015 * inputs - pointer to config item
3016 * - pointer to link count already on this conf
3017 * output - NONE
3018 * side effects - Add a connect block
3019 */
3020 int
3021 conf_add_server(struct ConfItem *conf, const char *class_name)
3022 {
3023 struct AccessItem *aconf;
3024 struct split_nuh_item nuh;
3025 char conf_user[USERLEN + 1];
3026 char conf_host[HOSTLEN + 1];
3027
3028 aconf = map_to_conf(conf);
3029
3030 conf_add_class_to_conf(conf, class_name);
3031
3032 if (!aconf->host || !conf->name)
3033 {
3034 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
3035 ilog(L_WARN, "Bad connect block");
3036 return -1;
3037 }
3038
3039 if (EmptyString(aconf->passwd) && !IsConfCryptLink(aconf))
3040 {
3041 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
3042 conf->name);
3043 ilog(L_WARN, "Bad connect block, host %s", conf->name);
3044 return -1;
3045 }
3046
3047 nuh.nuhmask = aconf->host;
3048 nuh.nickptr = NULL;
3049 nuh.userptr = conf_user;
3050 nuh.hostptr = conf_host;
3051
3052 nuh.nicksize = 0;
3053 nuh.usersize = sizeof(conf_user);
3054 nuh.hostsize = sizeof(conf_host);
3055
3056 split_nuh(&nuh);
3057
3058 MyFree(aconf->host);
3059 aconf->host = NULL;
3060
3061 DupString(aconf->user, conf_user); /* somehow username checking for servers
3062 got lost in H6/7, will have to be re-added */
3063 DupString(aconf->host, conf_host);
3064
3065 lookup_confhost(conf);
3066
3067 return 0;
3068 }
3069
3070 /* yyerror()
3071 *
3072 * inputs - message from parser
3073 * output - NONE
3074 * side effects - message to opers and log file entry is made
3075 */
3076 void
3077 yyerror(const char *msg)
3078 {
3079 char newlinebuf[IRCD_BUFSIZE];
3080
3081 if (conf_parser_ctx.pass != 1)
3082 return;
3083
3084 strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
3085 sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
3086 conffilebuf, lineno + 1, msg, newlinebuf);
3087 ilog(L_WARN, "\"%s\", line %u: %s: %s",
3088 conffilebuf, lineno + 1, msg, newlinebuf);
3089 }
3090
3091 int
3092 conf_fbgets(char *lbuf, unsigned int max_size, FBFILE *fb)
3093 {
3094 if (fbgets(lbuf, max_size, fb) == NULL)
3095 return 0;
3096
3097 return strlen(lbuf);
3098 }
3099
3100 int
3101 conf_yy_fatal_error(const char *msg)
3102 {
3103 return 0;
3104 }
3105
3106 /*
3107 * valid_tkline()
3108 *
3109 * inputs - pointer to ascii string to check
3110 * - whether the specified time is in seconds or minutes
3111 * output - -1 not enough parameters
3112 * - 0 if not an integer number, else the number
3113 * side effects - none
3114 * Originally written by Dianora (Diane, db@db.net)
3115 */
3116 time_t
3117 valid_tkline(char *p, int minutes)
3118 {
3119 time_t result = 0;
3120
3121 while (*p)
3122 {
3123 if (IsDigit(*p))
3124 {
3125 result *= 10;
3126 result += ((*p) & 0xF);
3127 p++;
3128 }
3129 else
3130 return 0;
3131 }
3132
3133 /* in the degenerate case where oper does a /quote kline 0 user@host :reason
3134 * i.e. they specifically use 0, I am going to return 1 instead
3135 * as a return value of non-zero is used to flag it as a temporary kline
3136 */
3137
3138 if (result == 0)
3139 result = 1;
3140
3141 /*
3142 * If the incoming time is in seconds convert it to minutes for the purpose
3143 * of this calculation
3144 */
3145 if (!minutes)
3146 result = result / (time_t)60;
3147
3148 if (result > MAX_TDKLINE_TIME)
3149 result = MAX_TDKLINE_TIME;
3150
3151 result = result * (time_t)60; /* turn it into seconds */
3152
3153 return result;
3154 }
3155
3156 /* valid_wild_card()
3157 *
3158 * input - pointer to client
3159 * - int flag, 0 for no warning oper 1 for warning oper
3160 * - count of following varargs to check
3161 * output - 0 if not valid, 1 if valid
3162 * side effects - NOTICE is given to source_p if warn is 1
3163 */
3164 int
3165 valid_wild_card(struct Client *source_p, int warn, int count, ...)
3166 {
3167 char *p;
3168 char tmpch;
3169 int nonwild = 0;
3170 va_list args;
3171
3172 /*
3173 * Now we must check the user and host to make sure there
3174 * are at least NONWILDCHARS non-wildcard characters in
3175 * them, otherwise assume they are attempting to kline
3176 * *@* or some variant of that. This code will also catch
3177 * people attempting to kline *@*.tld, as long as NONWILDCHARS
3178 * is greater than 3. In that case, there are only 3 non-wild
3179 * characters (tld), so if NONWILDCHARS is 4, the kline will
3180 * be disallowed.
3181 * -wnder
3182 */
3183
3184 va_start(args, count);
3185
3186 while (count--)
3187 {
3188 p = va_arg(args, char *);
3189 if (p == NULL)
3190 continue;
3191
3192 while ((tmpch = *p++))
3193 {
3194 if (!IsKWildChar(tmpch))
3195 {
3196 /*
3197 * If we find enough non-wild characters, we can
3198 * break - no point in searching further.
3199 */
3200 if (++nonwild >= ConfigFileEntry.min_nonwildcard)
3201 return 1;
3202 }
3203 }
3204 }
3205
3206 if (warn)
3207 sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
3208 me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
3209 return 0;
3210 }
3211
3212 /* XXX should this go into a separate file ? -Dianora */
3213 /* parse_aline
3214 *
3215 * input - pointer to cmd name being used
3216 * - pointer to client using cmd
3217 * - parc parameter count
3218 * - parv[] list of parameters to parse
3219 * - parse_flags bit map of things to test
3220 * - pointer to user or string to parse into
3221 * - pointer to host or NULL to parse into if non NULL
3222 * - pointer to optional tkline time or NULL
3223 * - pointer to target_server to parse into if non NULL
3224 * - pointer to reason to parse into
3225 *
3226 * output - 1 if valid, -1 if not valid
3227 * side effects - A generalised k/d/x etc. line parser,
3228 * "ALINE [time] user@host|string [ON] target :reason"
3229 * will parse returning a parsed user, host if
3230 * h_p pointer is non NULL, string otherwise.
3231 * if tkline_time pointer is non NULL a tk line will be set
3232 * to non zero if found.
3233 * if tkline_time pointer is NULL and tk line is found,
3234 * error is reported.
3235 * if target_server is NULL and an "ON" is found error
3236 * is reported.
3237 * if reason pointer is NULL ignore pointer,
3238 * this allows use of parse_a_line in unkline etc.
3239 *
3240 * - Dianora
3241 */
3242 int
3243 parse_aline(const char *cmd, struct Client *source_p,
3244 int parc, char **parv,
3245 int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
3246 char **target_server, char **reason)
3247 {
3248 int found_tkline_time=0;
3249 static char def_reason[] = "No Reason";
3250 static char user[USERLEN*4+1];
3251 static char host[HOSTLEN*4+1];
3252
3253 parv++;
3254 parc--;
3255
3256 found_tkline_time = valid_tkline(*parv, TK_MINUTES);
3257
3258 if (found_tkline_time != 0)
3259 {
3260 parv++;
3261 parc--;
3262
3263 if (tkline_time != NULL)
3264 *tkline_time = found_tkline_time;
3265 else
3266 {
3267 sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3268 me.name, source_p->name, cmd);
3269 return -1;
3270 }
3271 }
3272
3273 if (parc == 0)
3274 {
3275 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3276 me.name, source_p->name, cmd);
3277 return -1;
3278 }
3279
3280 if (h_p == NULL)
3281 *up_p = *parv;
3282 else
3283 {
3284 if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
3285 return -1;
3286
3287 *up_p = user;
3288 *h_p = host;
3289 }
3290
3291 parc--;
3292 parv++;
3293
3294 if (parc != 0)
3295 {
3296 if (irccmp(*parv, "ON") == 0)
3297 {
3298 parc--;
3299 parv++;
3300
3301 if (target_server == NULL)
3302 {
3303 sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
3304 me.name, source_p->name, cmd);
3305 return -1;
3306 }
3307
3308 if (!IsOperRemoteBan(source_p))
3309 {
3310 sendto_one(source_p, form_str(ERR_NOPRIVS),
3311 me.name, source_p->name, "remoteban");
3312 return -1;
3313 }
3314
3315 if (parc == 0 || EmptyString(*parv))
3316 {
3317 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3318 me.name, source_p->name, cmd);
3319 return -1;
3320 }
3321
3322 *target_server = *parv;
3323 parc--;
3324 parv++;
3325 }
3326 else
3327 {
3328 /* Make sure target_server *is* NULL if no ON server found
3329 * caller probably NULL'd it first, but no harm to do it again -db
3330 */
3331 if (target_server != NULL)
3332 *target_server = NULL;
3333 }
3334 }
3335
3336 if (h_p != NULL)
3337 {
3338 if (strchr(user, '!') != NULL)
3339 {
3340 sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3341 me.name, source_p->name);
3342 return -1;
3343 }
3344
3345 if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 2, *up_p, *h_p))
3346 return -1;
3347 }
3348 else
3349 if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 1, *up_p))
3350 return -1;
3351
3352 if (reason != NULL)
3353 {
3354 if (parc != 0 && !EmptyString(*parv))
3355 {
3356 *reason = *parv;
3357 if (!valid_comment(source_p, *reason, YES))
3358 return -1;
3359 }
3360 else
3361 *reason = def_reason;
3362 }
3363
3364 return 1;
3365 }
3366
3367 /* find_user_host()
3368 *
3369 * inputs - pointer to client placing kline
3370 * - pointer to user_host_or_nick
3371 * - pointer to user buffer
3372 * - pointer to host buffer
3373 * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
3374 * side effects -
3375 */
3376 static int
3377 find_user_host(struct Client *source_p, char *user_host_or_nick,
3378 char *luser, char *lhost, unsigned int flags)
3379 {
3380 struct Client *target_p = NULL;
3381 char *hostp = NULL;
3382
3383 if (lhost == NULL)
3384 {
3385 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
3386 return 1;
3387 }
3388
3389 if ((hostp = strchr(user_host_or_nick, '@')) || *user_host_or_nick == '*')
3390 {
3391 /* Explicit user@host mask given */
3392
3393 if (hostp != NULL) /* I'm a little user@host */
3394 {
3395 *(hostp++) = '\0'; /* short and squat */
3396 if (*user_host_or_nick)
3397 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
3398 else
3399 strcpy(luser, "*");
3400 if (*hostp)
3401 strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
3402 else
3403 strcpy(lhost, "*");
3404 }
3405 else
3406 {
3407 luser[0] = '*'; /* no @ found, assume its *@somehost */
3408 luser[1] = '\0';
3409 strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
3410 }
3411
3412 return 1;
3413 }
3414 else if (!(flags & NOUSERLOOKUP))
3415 {
3416 /* Try to find user@host mask from nick */
3417 /* Okay to use source_p as the first param, because source_p == client_p */
3418 if ((target_p =
3419 find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
3420 return 0;
3421
3422 if (IsExemptKline(target_p))
3423 {
3424 if (!IsServer(source_p))
3425 sendto_one(source_p,
3426 ":%s NOTICE %s :%s is E-lined",
3427 me.name, source_p->name, target_p->name);
3428 return 0;
3429 }
3430
3431 /*
3432 * turn the "user" bit into "*user", blow away '~'
3433 * if found in original user name (non-idented)
3434 */
3435 strlcpy(luser, target_p->username, USERLEN*4 + 1);
3436
3437 if (target_p->username[0] == '~')
3438 luser[0] = '*';
3439
3440 if (target_p->sockhost[0] == '\0' ||
3441 (target_p->sockhost[0] == '0' && target_p->sockhost[1] == '\0'))
3442 strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
3443 else
3444 strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
3445 return 1;
3446 }
3447
3448 return 0;
3449 }
3450
3451 /* valid_comment()
3452 *
3453 * inputs - pointer to client
3454 * - pointer to comment
3455 * output - 0 if no valid comment,
3456 * - 1 if valid
3457 * side effects - truncates reason where necessary
3458 */
3459 int
3460 valid_comment(struct Client *source_p, char *comment, int warn)
3461 {
3462 if (strchr(comment, '"'))
3463 {
3464 if (warn)
3465 sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3466 me.name, source_p->name);
3467 return 0;
3468 }
3469
3470 if (strlen(comment) > REASONLEN)
3471 comment[REASONLEN-1] = '\0';
3472
3473 return 1;
3474 }
3475
3476 /* match_conf_password()
3477 *
3478 * inputs - pointer to given password
3479 * - pointer to Conf
3480 * output - 1 or 0 if match
3481 * side effects - none
3482 */
3483 int
3484 match_conf_password(const char *password, const struct AccessItem *aconf)
3485 {
3486 const char *encr = NULL;
3487
3488 if (password == NULL || aconf->passwd == NULL)
3489 return 0;
3490
3491 if (aconf->flags & CONF_FLAGS_ENCRYPTED)
3492 {
3493 /* use first two chars of the password they send in as salt */
3494 /* If the password in the conf is MD5, and ircd is linked
3495 * to scrypt on FreeBSD, or the standard crypt library on
3496 * glibc Linux, then this code will work fine on generating
3497 * the proper encrypted hash for comparison.
3498 */
3499 if (*aconf->passwd)
3500 encr = crypt(password, aconf->passwd);
3501 else
3502 encr = "";
3503 }
3504 else
3505 encr = password;
3506
3507 return !strcmp(encr, aconf->passwd);
3508 }
3509
3510 /*
3511 * cluster_a_line
3512 *
3513 * inputs - client sending the cluster
3514 * - command name "KLINE" "XLINE" etc.
3515 * - capab -- CAP_KLN etc. from s_serv.h
3516 * - cluster type -- CLUSTER_KLINE etc. from s_conf.h
3517 * - pattern and args to send along
3518 * output - none
3519 * side effects - Take source_p send the pattern with args given
3520 * along to all servers that match capab and cluster type
3521 */
3522 void
3523 cluster_a_line(struct Client *source_p, const char *command,
3524 int capab, int cluster_type, const char *pattern, ...)
3525 {
3526 va_list args;
3527 char buffer[IRCD_BUFSIZE];
3528 const dlink_node *ptr = NULL;
3529
3530 va_start(args, pattern);
3531 vsnprintf(buffer, sizeof(buffer), pattern, args);
3532 va_end(args);
3533
3534 DLINK_FOREACH(ptr, cluster_items.head)
3535 {
3536 const struct ConfItem *conf = ptr->data;
3537
3538 if (conf->flags & cluster_type)
3539 sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
3540 "%s %s %s", command, conf->name, buffer);
3541 }
3542 }
3543
3544 /*
3545 * split_nuh
3546 *
3547 * inputs - pointer to original mask (modified in place)
3548 * - pointer to pointer where nick should go
3549 * - pointer to pointer where user should go
3550 * - pointer to pointer where host should go
3551 * output - NONE
3552 * side effects - mask is modified in place
3553 * If nick pointer is NULL, ignore writing to it
3554 * this allows us to use this function elsewhere.
3555 *
3556 * mask nick user host
3557 * ---------------------- ------- ------- ------
3558 * Dianora!db@db.net Dianora db db.net
3559 * Dianora Dianora * *
3560 * db.net * * db.net
3561 * OR if nick pointer is NULL
3562 * Dianora - * Dianora
3563 * Dianora! Dianora * *
3564 * Dianora!@ Dianora * *
3565 * Dianora!db Dianora db *
3566 * Dianora!@db.net Dianora * db.net
3567 * db@db.net * db db.net
3568 * !@ * * *
3569 * @ * * *
3570 * ! * * *
3571 */
3572 void
3573 split_nuh(struct split_nuh_item *const iptr)
3574 {
3575 char *p = NULL, *q = NULL;
3576
3577 if (iptr->nickptr)
3578 strlcpy(iptr->nickptr, "*", iptr->nicksize);
3579 if (iptr->userptr)
3580 strlcpy(iptr->userptr, "*", iptr->usersize);
3581 if (iptr->hostptr)
3582 strlcpy(iptr->hostptr, "*", iptr->hostsize);
3583
3584 if ((p = strchr(iptr->nuhmask, '!')))
3585 {
3586 *p = '\0';
3587
3588 if (iptr->nickptr && *iptr->nuhmask != '\0')
3589 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3590
3591 if ((q = strchr(++p, '@'))) {
3592 *q++ = '\0';
3593
3594 if (*p != '\0')
3595 strlcpy(iptr->userptr, p, iptr->usersize);
3596
3597 if (*q != '\0')
3598 strlcpy(iptr->hostptr, q, iptr->hostsize);
3599 }
3600 else
3601 {
3602 if (*p != '\0')
3603 strlcpy(iptr->userptr, p, iptr->usersize);
3604 }
3605 }
3606 else
3607 {
3608 /* No ! found so lets look for a user@host */
3609 if ((p = strchr(iptr->nuhmask, '@')))
3610 {
3611 /* if found a @ */
3612 *p++ = '\0';
3613
3614 if (*iptr->nuhmask != '\0')
3615 strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
3616
3617 if (*p != '\0')
3618 strlcpy(iptr->hostptr, p, iptr->hostsize);
3619 }
3620 else
3621 {
3622 /* no @ found */
3623 if (!iptr->nickptr || strpbrk(iptr->nuhmask, ".:"))
3624 strlcpy(iptr->hostptr, iptr->nuhmask, iptr->hostsize);
3625 else
3626 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3627 }
3628 }
3629 }
3630
3631 /*
3632 * flags_to_ascii
3633 *
3634 * inputs - flags is a bitmask
3635 * - pointer to table of ascii letters corresponding
3636 * to each bit
3637 * - flag 1 for convert ToLower if bit missing
3638 * 0 if ignore.
3639 * output - none
3640 * side effects - string pointed to by p has bitmap chars written to it
3641 */
3642 static void
3643 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3644 int lowerit)
3645 {
3646 unsigned int mask = 1;
3647 int i = 0;
3648
3649 for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3650 {
3651 if (flags & mask)
3652 *p++ = bit_table[i];
3653 else if (lowerit)
3654 *p++ = ToLower(bit_table[i]);
3655 }
3656 *p = '\0';
3657 }
3658
3659 /*
3660 * cidr_limit_reached
3661 *
3662 * inputs - int flag allowing over_rule of limits
3663 * - pointer to the ip to be added
3664 * - pointer to the class
3665 * output - non zero if limit reached
3666 * 0 if limit not reached
3667 * side effects -
3668 */
3669 static int
3670 cidr_limit_reached(int over_rule,
3671 struct irc_ssaddr *ip, struct ClassItem *aclass)
3672 {
3673 dlink_node *ptr = NULL;
3674 struct CidrItem *cidr;
3675
3676 if (NumberPerCidr(aclass) <= 0)
3677 return 0;
3678
3679 if (ip->ss.ss_family == AF_INET)
3680 {
3681 if (CidrBitlenIPV4(aclass) <= 0)
3682 return 0;
3683
3684 DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3685 {
3686 cidr = ptr->data;
3687 if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3688 {
3689 if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3690 return -1;
3691 cidr->number_on_this_cidr++;
3692 return 0;
3693 }
3694 }
3695 cidr = MyMalloc(sizeof(struct CidrItem));
3696 cidr->number_on_this_cidr = 1;
3697 cidr->mask = *ip;
3698 mask_addr(&cidr->mask, CidrBitlenIPV4(aclass));
3699 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3700 }
3701 #ifdef IPV6
3702 else if (CidrBitlenIPV6(aclass) > 0)
3703 {
3704 DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3705 {
3706 cidr = ptr->data;
3707 if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3708 {
3709 if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3710 return -1;
3711 cidr->number_on_this_cidr++;
3712 return 0;
3713 }
3714 }
3715 cidr = MyMalloc(sizeof(struct CidrItem));
3716 cidr->number_on_this_cidr = 1;
3717 cidr->mask = *ip;
3718 mask_addr(&cidr->mask, CidrBitlenIPV6(aclass));
3719 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3720 }
3721 #endif
3722 return 0;
3723 }
3724
3725 /*
3726 * remove_from_cidr_check
3727 *
3728 * inputs - pointer to the ip to be removed
3729 * - pointer to the class
3730 * output - NONE
3731 * side effects -
3732 */
3733 static void
3734 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3735 {
3736 dlink_node *ptr = NULL;
3737 dlink_node *next_ptr = NULL;
3738 struct CidrItem *cidr;
3739
3740 if (NumberPerCidr(aclass) == 0)
3741 return;
3742
3743 if (ip->ss.ss_family == AF_INET)
3744 {
3745 if (CidrBitlenIPV4(aclass) <= 0)
3746 return;
3747
3748 DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3749 {
3750 cidr = ptr->data;
3751 if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3752 {
3753 cidr->number_on_this_cidr--;
3754 if (cidr->number_on_this_cidr == 0)
3755 {
3756 dlinkDelete(ptr, &aclass->list_ipv4);
3757 MyFree(cidr);
3758 return;
3759 }
3760 }
3761 }
3762 }
3763 #ifdef IPV6
3764 else if (CidrBitlenIPV6(aclass) > 0)
3765 {
3766 DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3767 {
3768 cidr = ptr->data;
3769 if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3770 {
3771 cidr->number_on_this_cidr--;
3772 if (cidr->number_on_this_cidr == 0)
3773 {
3774 dlinkDelete(ptr, &aclass->list_ipv6);
3775 MyFree(cidr);
3776 return;
3777 }
3778 }
3779 }
3780 }
3781 #endif
3782 }
3783
3784 static void
3785 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3786 dlink_list *old_list, dlink_list *new_list, int changed)
3787 {
3788 dlink_node *ptr;
3789 struct Client *client_p;
3790 struct ConfItem *conf;
3791 struct AccessItem *aconf;
3792
3793 if (!changed)
3794 {
3795 *new_list = *old_list;
3796 old_list->head = old_list->tail = NULL;
3797 old_list->length = 0;
3798 return;
3799 }
3800
3801 DLINK_FOREACH(ptr, local_client_list.head)
3802 {
3803 client_p = ptr->data;
3804 if (client_p->localClient->aftype != aftype)
3805 continue;
3806 if (dlink_list_length(&client_p->localClient->confs) == 0)
3807 continue;
3808
3809 conf = client_p->localClient->confs.tail->data;
3810 if (conf->type == CLIENT_TYPE)
3811 {
3812 aconf = map_to_conf(conf);
3813 if (aconf->class_ptr == oldcl)
3814 cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3815 }
3816 }
3817 }
3818
3819 /*
3820 * rebuild_cidr_class
3821 *
3822 * inputs - pointer to old conf
3823 * - pointer to new_class
3824 * output - none
3825 * side effects - rebuilds the class link list of cidr blocks
3826 */
3827 void
3828 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3829 {
3830 struct ClassItem *old_class = map_to_conf(conf);
3831
3832 if (NumberPerCidr(old_class) > 0 && NumberPerCidr(new_class) > 0)
3833 {
3834 if (CidrBitlenIPV4(old_class) > 0 && CidrBitlenIPV4(new_class) > 0)
3835 rebuild_cidr_list(AF_INET, conf, new_class,
3836 &old_class->list_ipv4, &new_class->list_ipv4,
3837 CidrBitlenIPV4(old_class) != CidrBitlenIPV4(new_class));
3838
3839 #ifdef IPV6
3840 if (CidrBitlenIPV6(old_class) > 0 && CidrBitlenIPV6(new_class) > 0)
3841 rebuild_cidr_list(AF_INET6, conf, new_class,
3842 &old_class->list_ipv6, &new_class->list_ipv6,
3843 CidrBitlenIPV6(old_class) != CidrBitlenIPV6(new_class));
3844 #endif
3845 }
3846
3847 destroy_cidr_class(old_class);
3848 }
3849
3850 /*
3851 * destroy_cidr_list
3852 *
3853 * inputs - pointer to class dlink list of cidr blocks
3854 * output - none
3855 * side effects - completely destroys the class link list of cidr blocks
3856 */
3857 static void
3858 destroy_cidr_list(dlink_list *list)
3859 {
3860 dlink_node *ptr = NULL, *next_ptr = NULL;
3861
3862 DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3863 {
3864 dlinkDelete(ptr, list);
3865 MyFree(ptr->data);
3866 }
3867 }
3868
3869 /*
3870 * destroy_cidr_class
3871 *
3872 * inputs - pointer to class
3873 * output - none
3874 * side effects - completely destroys the class link list of cidr blocks
3875 */
3876 static void
3877 destroy_cidr_class(struct ClassItem *aclass)
3878 {
3879 destroy_cidr_list(&aclass->list_ipv4);
3880 destroy_cidr_list(&aclass->list_ipv6);
3881 }

Properties

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