ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1121
Committed: Sun Jan 9 11:03:03 2011 UTC (14 years, 7 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.3/src/s_conf.c
File size: 99203 byte(s)
Log Message:
- removed all instances of STATIC_MODULES since we don't have
  static modules anymore
- removed m_mkpasswd module from contrib

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 load_conf_modules();
1763
1764 flush_deleted_I_P();
1765
1766 rehashed_klines = 1;
1767
1768 if (ConfigLoggingEntry.use_logging)
1769 reopen_log(logFileName);
1770
1771 return(0);
1772 }
1773
1774 /* set_default_conf()
1775 *
1776 * inputs - NONE
1777 * output - NONE
1778 * side effects - Set default values here.
1779 * This is called **PRIOR** to parsing the
1780 * configuration file. If you want to do some validation
1781 * of values later, put them in validate_conf().
1782 */
1783 static void
1784 set_default_conf(void)
1785 {
1786 /* verify init_class() ran, this should be an unnecessary check
1787 * but its not much work.
1788 */
1789 assert(class_default == (struct ConfItem *) class_items.tail->data);
1790
1791 #ifdef HAVE_LIBCRYPTO
1792 ServerInfo.rsa_private_key = NULL;
1793 ServerInfo.rsa_private_key_file = NULL;
1794 #endif
1795
1796 /* ServerInfo.name is not rehashable */
1797 /* ServerInfo.name = ServerInfo.name; */
1798 ServerInfo.description = NULL;
1799 DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1800 DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1801
1802 memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1803 ServerInfo.specific_ipv4_vhost = 0;
1804 memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
1805 ServerInfo.specific_ipv6_vhost = 0;
1806
1807 ServerInfo.max_clients = MAXCLIENTS_MAX;
1808
1809 ServerInfo.hub = 0;
1810 ServerInfo.dns_host.sin_addr.s_addr = 0;
1811 ServerInfo.dns_host.sin_port = 0;
1812 AdminInfo.name = NULL;
1813 AdminInfo.email = NULL;
1814 AdminInfo.description = NULL;
1815
1816 set_log_level(L_NOTICE);
1817 ConfigLoggingEntry.use_logging = 1;
1818 ConfigLoggingEntry.operlog[0] = '\0';
1819 ConfigLoggingEntry.userlog[0] = '\0';
1820 ConfigLoggingEntry.klinelog[0] = '\0';
1821 ConfigLoggingEntry.glinelog[0] = '\0';
1822 ConfigLoggingEntry.killlog[0] = '\0';
1823 ConfigLoggingEntry.operspylog[0] = '\0';
1824 ConfigLoggingEntry.ioerrlog[0] = '\0';
1825 ConfigLoggingEntry.failed_operlog[0] = '\0';
1826
1827 ConfigChannel.disable_fake_channels = NO;
1828 ConfigChannel.restrict_channels = NO;
1829 ConfigChannel.disable_local_channels = NO;
1830 ConfigChannel.use_invex = YES;
1831 ConfigChannel.use_except = YES;
1832 ConfigChannel.use_knock = YES;
1833 ConfigChannel.knock_delay = 300;
1834 ConfigChannel.knock_delay_channel = 60;
1835 ConfigChannel.max_chans_per_user = 15;
1836 ConfigChannel.quiet_on_ban = YES;
1837 ConfigChannel.max_bans = 25;
1838 ConfigChannel.default_split_user_count = 0;
1839 ConfigChannel.default_split_server_count = 0;
1840 ConfigChannel.no_join_on_split = NO;
1841 ConfigChannel.no_create_on_split = NO;
1842 ConfigChannel.burst_topicwho = YES;
1843
1844 ConfigServerHide.flatten_links = NO;
1845 ConfigServerHide.links_delay = 300;
1846 ConfigServerHide.hidden = NO;
1847 ConfigServerHide.disable_hidden = NO;
1848 ConfigServerHide.hide_servers = NO;
1849 DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1850 ConfigServerHide.hide_server_ips = NO;
1851
1852
1853 ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1854 ConfigFileEntry.gline_min_cidr = 16;
1855 ConfigFileEntry.gline_min_cidr6 = 48;
1856 ConfigFileEntry.invisible_on_connect = YES;
1857 ConfigFileEntry.burst_away = NO;
1858 ConfigFileEntry.use_whois_actually = YES;
1859 ConfigFileEntry.tkline_expire_notices = YES;
1860 ConfigFileEntry.hide_spoof_ips = YES;
1861 ConfigFileEntry.ignore_bogus_ts = NO;
1862 ConfigFileEntry.disable_auth = NO;
1863 ConfigFileEntry.disable_remote = NO;
1864 ConfigFileEntry.kill_chase_time_limit = 90;
1865 ConfigFileEntry.default_floodcount = 8;
1866 ConfigFileEntry.failed_oper_notice = YES;
1867 ConfigFileEntry.dots_in_ident = 0;
1868 ConfigFileEntry.min_nonwildcard = 4;
1869 ConfigFileEntry.min_nonwildcard_simple = 3;
1870 ConfigFileEntry.max_accept = 20;
1871 ConfigFileEntry.anti_nick_flood = NO;
1872 ConfigFileEntry.max_nick_time = 20;
1873 ConfigFileEntry.max_nick_changes = 5;
1874 ConfigFileEntry.anti_spam_exit_message_time = 0;
1875 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1876 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1877 ConfigFileEntry.kline_with_reason = YES;
1878 ConfigFileEntry.kline_reason = NULL;
1879 ConfigFileEntry.warn_no_nline = YES;
1880 ConfigFileEntry.stats_o_oper_only = NO;
1881 ConfigFileEntry.stats_k_oper_only = 1; /* masked */
1882 ConfigFileEntry.stats_i_oper_only = 1; /* masked */
1883 ConfigFileEntry.stats_P_oper_only = NO;
1884 ConfigFileEntry.caller_id_wait = 60;
1885 ConfigFileEntry.opers_bypass_callerid = NO;
1886 ConfigFileEntry.pace_wait = 10;
1887 ConfigFileEntry.pace_wait_simple = 1;
1888 ConfigFileEntry.short_motd = NO;
1889 ConfigFileEntry.ping_cookie = NO;
1890 ConfigFileEntry.no_oper_flood = NO;
1891 ConfigFileEntry.true_no_oper_flood = NO;
1892 ConfigFileEntry.oper_pass_resv = YES;
1893 ConfigFileEntry.glines = NO;
1894 ConfigFileEntry.gline_time = 12 * 3600;
1895 ConfigFileEntry.idletime = 0;
1896 ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1897 ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1898 ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1899 ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1900 UMODE_OPERWALL | UMODE_WALLOP;
1901 DupString(ConfigFileEntry.servlink_path, SLPATH);
1902 #ifdef HAVE_LIBCRYPTO
1903 /* jdc -- This is our default value for a cipher. According to the
1904 * CRYPTLINK document (doc/cryptlink.txt), BF/128 must be supported
1905 * under all circumstances if cryptlinks are enabled. So,
1906 * this will be our default.
1907 *
1908 * NOTE: I apologise for the hard-coded value of "1" (BF/128).
1909 * This should be moved into a find_cipher() routine.
1910 */
1911 ConfigFileEntry.default_cipher_preference = &CipherTable[1];
1912 #endif
1913 ConfigFileEntry.use_egd = NO;
1914 ConfigFileEntry.egdpool_path = NULL;
1915 #ifdef HAVE_LIBZ
1916 ConfigFileEntry.compression_level = 0;
1917 #endif
1918 ConfigFileEntry.throttle_time = 10;
1919 }
1920
1921 /* read_conf()
1922 *
1923 * inputs - file descriptor pointing to config file to use
1924 * output - None
1925 * side effects - Read configuration file.
1926 */
1927 static void
1928 read_conf(FBFILE *file)
1929 {
1930 lineno = 0;
1931
1932 set_default_conf(); /* Set default values prior to conf parsing */
1933 conf_parser_ctx.pass = 1;
1934 yyparse(); /* pick up the classes first */
1935
1936 fbrewind(file);
1937
1938 conf_parser_ctx.pass = 2;
1939 yyparse(); /* Load the values from the conf */
1940 validate_conf(); /* Check to make sure some values are still okay. */
1941 /* Some global values are also loaded here. */
1942 check_class(); /* Make sure classes are valid */
1943 }
1944
1945 static void
1946 validate_conf(void)
1947 {
1948 if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1949 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1950
1951 if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1952 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1953
1954 if (ConfigFileEntry.servlink_path == NULL)
1955 DupString(ConfigFileEntry.servlink_path, SLPATH);
1956
1957 if (ServerInfo.network_name == NULL)
1958 DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1959
1960 if (ServerInfo.network_desc == NULL)
1961 DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1962
1963 if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1964 (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1965 ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1966
1967 ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1968 }
1969
1970 /* lookup_confhost()
1971 *
1972 * start DNS lookups of all hostnames in the conf
1973 * line and convert an IP addresses in a.b.c.d number for to IP#s.
1974 */
1975 static void
1976 lookup_confhost(struct ConfItem *conf)
1977 {
1978 struct AccessItem *aconf;
1979 struct addrinfo hints, *res;
1980
1981 aconf = map_to_conf(conf);
1982
1983 if (EmptyString(aconf->host) ||
1984 EmptyString(aconf->user))
1985 {
1986 ilog(L_ERROR, "Host/server name error: (%s) (%s)",
1987 aconf->host, conf->name);
1988 return;
1989 }
1990
1991 if (strchr(aconf->host, '*') ||
1992 strchr(aconf->host, '?'))
1993 return;
1994
1995 /* Do name lookup now on hostnames given and store the
1996 * ip numbers in conf structure.
1997 */
1998 memset(&hints, 0, sizeof(hints));
1999
2000 hints.ai_family = AF_UNSPEC;
2001 hints.ai_socktype = SOCK_STREAM;
2002
2003 /* Get us ready for a bind() and don't bother doing dns lookup */
2004 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
2005
2006 if (irc_getaddrinfo(aconf->host, NULL, &hints, &res))
2007 {
2008 conf_dns_lookup(aconf);
2009 return;
2010 }
2011
2012 assert(res != NULL);
2013
2014 memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
2015 aconf->ipnum.ss_len = res->ai_addrlen;
2016 aconf->ipnum.ss.ss_family = res->ai_family;
2017 irc_freeaddrinfo(res);
2018 }
2019
2020 /* conf_connect_allowed()
2021 *
2022 * inputs - pointer to inaddr
2023 * - int type ipv4 or ipv6
2024 * output - BANNED or accepted
2025 * side effects - none
2026 */
2027 int
2028 conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
2029 {
2030 struct ip_entry *ip_found;
2031 struct AccessItem *aconf = find_dline_conf(addr, aftype);
2032
2033 /* DLINE exempt also gets you out of static limits/pacing... */
2034 if (aconf && (aconf->status & CONF_EXEMPTDLINE))
2035 return 0;
2036
2037 if (aconf != NULL)
2038 return BANNED_CLIENT;
2039
2040 ip_found = find_or_add_ip(addr);
2041
2042 if ((CurrentTime - ip_found->last_attempt) <
2043 ConfigFileEntry.throttle_time)
2044 {
2045 ip_found->last_attempt = CurrentTime;
2046 return TOO_FAST;
2047 }
2048
2049 ip_found->last_attempt = CurrentTime;
2050 return 0;
2051 }
2052
2053 static struct AccessItem *
2054 find_regexp_kline(const char *uhi[])
2055 {
2056 #ifdef HAVE_LIBPCRE
2057 const dlink_node *ptr = NULL;
2058
2059 DLINK_FOREACH(ptr, rkconf_items.head)
2060 {
2061 struct AccessItem *aptr = map_to_conf(ptr->data);
2062
2063 assert(aptr->regexuser);
2064 assert(aptr->regexhost);
2065
2066 if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2067 (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2068 !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2069 return aptr;
2070 }
2071 #endif
2072 return NULL;
2073 }
2074
2075 /* find_kill()
2076 *
2077 * inputs - pointer to client structure
2078 * output - pointer to struct AccessItem if found
2079 * side effects - See if this user is klined already,
2080 * and if so, return struct AccessItem pointer
2081 */
2082 struct AccessItem *
2083 find_kill(struct Client *client_p)
2084 {
2085 struct AccessItem *aconf = NULL;
2086 const char *uhi[3];
2087
2088 uhi[0] = client_p->username;
2089 uhi[1] = client_p->host;
2090 uhi[2] = client_p->sockhost;
2091
2092 assert(client_p != NULL);
2093
2094 aconf = find_kline_conf(client_p->host, client_p->username,
2095 &client_p->localClient->ip,
2096 client_p->localClient->aftype);
2097 if (aconf == NULL)
2098 aconf = find_regexp_kline(uhi);
2099
2100 if (aconf && (aconf->status & CONF_KLINE))
2101 return aconf;
2102
2103 return NULL;
2104 }
2105
2106 struct AccessItem *
2107 find_gline(struct Client *client_p)
2108 {
2109 struct AccessItem *aconf;
2110
2111 assert(client_p != NULL);
2112
2113 aconf = find_gline_conf(client_p->host, client_p->username,
2114 &client_p->localClient->ip,
2115 client_p->localClient->aftype);
2116
2117 if (aconf && (aconf->status & CONF_GLINE))
2118 return aconf;
2119
2120 return NULL;
2121 }
2122
2123 /* add_temp_line()
2124 *
2125 * inputs - pointer to struct ConfItem
2126 * output - none
2127 * Side effects - links in given struct ConfItem into
2128 * temporary *line link list
2129 */
2130 void
2131 add_temp_line(struct ConfItem *conf)
2132 {
2133 struct AccessItem *aconf;
2134
2135 if (conf->type == DLINE_TYPE)
2136 {
2137 aconf = map_to_conf(conf);
2138 SetConfTemporary(aconf);
2139 dlinkAdd(conf, &conf->node, &temporary_dlines);
2140 MyFree(aconf->user);
2141 aconf->user = NULL;
2142 add_conf_by_address(CONF_DLINE, aconf);
2143 }
2144 else if (conf->type == KLINE_TYPE)
2145 {
2146 aconf = map_to_conf(conf);
2147 SetConfTemporary(aconf);
2148 dlinkAdd(conf, &conf->node, &temporary_klines);
2149 add_conf_by_address(CONF_KILL, aconf);
2150 }
2151 else if (conf->type == GLINE_TYPE)
2152 {
2153 aconf = map_to_conf(conf);
2154 SetConfTemporary(aconf);
2155 dlinkAdd(conf, &conf->node, &temporary_glines);
2156 add_conf_by_address(CONF_GLINE, aconf);
2157 }
2158 else if (conf->type == XLINE_TYPE)
2159 {
2160 conf->flags |= CONF_FLAGS_TEMPORARY;
2161 dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2162 }
2163 else if (conf->type == RXLINE_TYPE)
2164 {
2165 conf->flags |= CONF_FLAGS_TEMPORARY;
2166 dlinkAdd(conf, make_dlink_node(), &temporary_rxlines);
2167 }
2168 else if (conf->type == RKLINE_TYPE)
2169 {
2170 conf->flags |= CONF_FLAGS_TEMPORARY;
2171 dlinkAdd(conf, make_dlink_node(), &temporary_rklines);
2172 }
2173 else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2174 {
2175 conf->flags |= CONF_FLAGS_TEMPORARY;
2176 dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2177 }
2178 }
2179
2180 /* cleanup_tklines()
2181 *
2182 * inputs - NONE
2183 * output - NONE
2184 * side effects - call function to expire temporary k/d lines
2185 * This is an event started off in ircd.c
2186 */
2187 void
2188 cleanup_tklines(void *notused)
2189 {
2190 expire_tklines(&temporary_glines);
2191 expire_tklines(&temporary_klines);
2192 expire_tklines(&temporary_dlines);
2193 expire_tklines(&temporary_xlines);
2194 expire_tklines(&temporary_rxlines);
2195 expire_tklines(&temporary_rklines);
2196 expire_tklines(&temporary_resv);
2197 }
2198
2199 /* expire_tklines()
2200 *
2201 * inputs - tkline list pointer
2202 * output - NONE
2203 * side effects - expire tklines
2204 */
2205 static void
2206 expire_tklines(dlink_list *tklist)
2207 {
2208 dlink_node *ptr;
2209 dlink_node *next_ptr;
2210 struct ConfItem *conf;
2211 struct MatchItem *xconf;
2212 struct MatchItem *nconf;
2213 struct AccessItem *aconf;
2214 struct ResvChannel *cconf;
2215
2216 DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
2217 {
2218 conf = ptr->data;
2219 if (conf->type == GLINE_TYPE ||
2220 conf->type == KLINE_TYPE ||
2221 conf->type == DLINE_TYPE)
2222 {
2223 aconf = (struct AccessItem *)map_to_conf(conf);
2224 if (aconf->hold <= CurrentTime)
2225 {
2226 /* XXX - Do we want GLINE expiry notices?? */
2227 /* Alert opers that a TKline expired - Hwy */
2228 if (ConfigFileEntry.tkline_expire_notices)
2229 {
2230 if (aconf->status & CONF_KILL)
2231 {
2232 sendto_realops_flags(UMODE_ALL, L_ALL,
2233 "Temporary K-line for [%s@%s] expired",
2234 (aconf->user) ? aconf->user : "*",
2235 (aconf->host) ? aconf->host : "*");
2236 }
2237 else if (conf->type == DLINE_TYPE)
2238 {
2239 sendto_realops_flags(UMODE_ALL, L_ALL,
2240 "Temporary D-line for [%s] expired",
2241 (aconf->host) ? aconf->host : "*");
2242 }
2243 }
2244
2245 dlinkDelete(ptr, tklist);
2246 delete_one_address_conf(aconf->host, aconf);
2247 }
2248 }
2249 else if (conf->type == XLINE_TYPE ||
2250 conf->type == RXLINE_TYPE)
2251 {
2252 xconf = (struct MatchItem *)map_to_conf(conf);
2253 if (xconf->hold <= CurrentTime)
2254 {
2255 if (ConfigFileEntry.tkline_expire_notices)
2256 sendto_realops_flags(UMODE_ALL, L_ALL,
2257 "Temporary X-line for [%s] %sexpired", conf->name,
2258 conf->type == RXLINE_TYPE ? "(REGEX) " : "");
2259 dlinkDelete(ptr, tklist);
2260 free_dlink_node(ptr);
2261 delete_conf_item(conf);
2262 }
2263 }
2264 else if (conf->type == RKLINE_TYPE)
2265 {
2266 aconf = map_to_conf(conf);
2267 if (aconf->hold <= CurrentTime)
2268 {
2269 if (ConfigFileEntry.tkline_expire_notices)
2270 sendto_realops_flags(UMODE_ALL, L_ALL,
2271 "Temporary K-line for [%s@%s] (REGEX) expired",
2272 (aconf->user) ? aconf->user : "*",
2273 (aconf->host) ? aconf->host : "*");
2274 dlinkDelete(ptr, tklist);
2275 free_dlink_node(ptr);
2276 delete_conf_item(conf);
2277 }
2278 }
2279 else if (conf->type == NRESV_TYPE)
2280 {
2281 nconf = (struct MatchItem *)map_to_conf(conf);
2282 if (nconf->hold <= CurrentTime)
2283 {
2284 if (ConfigFileEntry.tkline_expire_notices)
2285 sendto_realops_flags(UMODE_ALL, L_ALL,
2286 "Temporary RESV for [%s] expired", conf->name);
2287 dlinkDelete(ptr, tklist);
2288 free_dlink_node(ptr);
2289 delete_conf_item(conf);
2290 }
2291 }
2292 else if (conf->type == CRESV_TYPE)
2293 {
2294 cconf = (struct ResvChannel *)map_to_conf(conf);
2295 if (cconf->hold <= CurrentTime)
2296 {
2297 if (ConfigFileEntry.tkline_expire_notices)
2298 sendto_realops_flags(UMODE_ALL, L_ALL,
2299 "Temporary RESV for [%s] expired", cconf->name);
2300 delete_channel_resv(cconf);
2301 }
2302 }
2303 }
2304 }
2305
2306 /* oper_privs_as_string()
2307 *
2308 * inputs - pointer to client_p
2309 * output - pointer to static string showing oper privs
2310 * side effects - return as string, the oper privs as derived from port
2311 */
2312 static const struct oper_privs
2313 {
2314 const unsigned int oprivs;
2315 const unsigned int hidden;
2316 const unsigned char c;
2317 } flag_list[] = {
2318 { OPER_FLAG_ADMIN, OPER_FLAG_HIDDEN_ADMIN, 'A' },
2319 { OPER_FLAG_REMOTEBAN, 0, 'B' },
2320 { OPER_FLAG_DIE, 0, 'D' },
2321 { OPER_FLAG_GLINE, 0, 'G' },
2322 { OPER_FLAG_REHASH, 0, 'H' },
2323 { OPER_FLAG_K, 0, 'K' },
2324 { OPER_FLAG_OPERWALL, 0, 'L' },
2325 { OPER_FLAG_N, 0, 'N' },
2326 { OPER_FLAG_GLOBAL_KILL, 0, 'O' },
2327 { OPER_FLAG_REMOTE, 0, 'R' },
2328 { OPER_FLAG_OPER_SPY, 0, 'S' },
2329 { OPER_FLAG_UNKLINE, 0, 'U' },
2330 { OPER_FLAG_X, 0, 'X' },
2331 { 0, 0, '\0' }
2332 };
2333
2334 char *
2335 oper_privs_as_string(const unsigned int port)
2336 {
2337 static char privs_out[16];
2338 char *privs_ptr = privs_out;
2339 unsigned int i = 0;
2340
2341 for (; flag_list[i].oprivs; ++i)
2342 {
2343 if ((port & flag_list[i].oprivs) &&
2344 (port & flag_list[i].hidden) == 0)
2345 *privs_ptr++ = flag_list[i].c;
2346 else
2347 *privs_ptr++ = ToLowerTab[flag_list[i].c];
2348 }
2349
2350 *privs_ptr = '\0';
2351
2352 return privs_out;
2353 }
2354
2355 /*
2356 * Input: A client to find the active oper{} name for.
2357 * Output: The nick!user@host{oper} of the oper.
2358 * "oper" is server name for remote opers
2359 * Side effects: None.
2360 */
2361 char *
2362 get_oper_name(const struct Client *client_p)
2363 {
2364 dlink_node *cnode;
2365 struct ConfItem *conf;
2366 struct AccessItem *aconf;
2367
2368 /* +5 for !,@,{,} and null */
2369 static char buffer[NICKLEN+USERLEN+HOSTLEN+HOSTLEN+5];
2370
2371 if (MyConnect(client_p))
2372 {
2373 DLINK_FOREACH(cnode, client_p->localClient->confs.head)
2374 {
2375 conf = cnode->data;
2376 aconf = map_to_conf(conf);
2377
2378 if (IsConfOperator(aconf))
2379 {
2380 ircsprintf(buffer, "%s!%s@%s{%s}", client_p->name,
2381 client_p->username, client_p->host,
2382 conf->name);
2383 return buffer;
2384 }
2385 }
2386
2387 /* Probably should assert here for now. If there is an oper out there
2388 * with no oper{} conf attached, it would be good for us to know...
2389 */
2390 assert(0); /* Oper without oper conf! */
2391 }
2392
2393 ircsprintf(buffer, "%s!%s@%s{%s}", client_p->name,
2394 client_p->username, client_p->host, client_p->servptr->name);
2395 return buffer;
2396 }
2397
2398 /* read_conf_files()
2399 *
2400 * inputs - cold start YES or NO
2401 * output - none
2402 * side effects - read all conf files needed, ircd.conf kline.conf etc.
2403 */
2404 void
2405 read_conf_files(int cold)
2406 {
2407 const char *filename;
2408 char chanmodes[32];
2409 char chanlimit[32];
2410
2411 conf_parser_ctx.boot = cold;
2412 filename = get_conf_name(CONF_TYPE);
2413
2414 /* We need to know the initial filename for the yyerror() to report
2415 FIXME: The full path is in conffilenamebuf first time since we
2416 dont know anything else
2417
2418 - Gozem 2002-07-21
2419 */
2420 strlcpy(conffilebuf, filename, sizeof(conffilebuf));
2421
2422 if ((conf_parser_ctx.conf_file = fbopen(filename, "r")) == NULL)
2423 {
2424 if (cold)
2425 {
2426 ilog(L_CRIT, "Unable to read configuration file '%s': %s",
2427 filename, strerror(errno));
2428 exit(-1);
2429 }
2430 else
2431 {
2432 sendto_realops_flags(UMODE_ALL, L_ALL,
2433 "Unable to read configuration file '%s': %s",
2434 filename, strerror(errno));
2435 return;
2436 }
2437 }
2438
2439 if (!cold)
2440 clear_out_old_conf();
2441
2442 read_conf(conf_parser_ctx.conf_file);
2443 fbclose(conf_parser_ctx.conf_file);
2444
2445 add_isupport("NETWORK", ServerInfo.network_name, -1);
2446 ircsprintf(chanmodes, "b%s%s:%d", ConfigChannel.use_except ? "e" : "",
2447 ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
2448 add_isupport("MAXLIST", chanmodes, -1);
2449 add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
2450 if (ConfigChannel.disable_local_channels)
2451 add_isupport("CHANTYPES", "#", -1);
2452 else
2453 add_isupport("CHANTYPES", "#&", -1);
2454 ircsprintf(chanlimit, "%s:%d", ConfigChannel.disable_local_channels ? "#" : "#&",
2455 ConfigChannel.max_chans_per_user);
2456 add_isupport("CHANLIMIT", chanlimit, -1);
2457 ircsprintf(chanmodes, "%s%s%s", ConfigChannel.use_except ? "e" : "",
2458 ConfigChannel.use_invex ? "I" : "", "b,k,l,imnpst");
2459 add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2460 if (ConfigChannel.use_except)
2461 add_isupport("EXCEPTS", "e", -1);
2462 if (ConfigChannel.use_invex)
2463 add_isupport("INVEX", "I", -1);
2464 add_isupport("CHANMODES", chanmodes, -1);
2465
2466 /*
2467 * message_locale may have changed. rebuild isupport since it relies
2468 * on strlen(form_str(RPL_ISUPPORT))
2469 */
2470 rebuild_isupport_message_line();
2471
2472 #ifdef HAVE_LIBPCRE
2473 parse_conf_file(RKLINE_TYPE, cold);
2474 parse_conf_file(RXLINE_TYPE, cold);
2475 #endif
2476 parse_conf_file(KLINE_TYPE, cold);
2477 parse_conf_file(DLINE_TYPE, cold);
2478 parse_conf_file(XLINE_TYPE, cold);
2479 parse_conf_file(NRESV_TYPE, cold);
2480 parse_conf_file(CRESV_TYPE, cold);
2481 }
2482
2483 /* parse_conf_file()
2484 *
2485 * inputs - type of conf file to parse
2486 * output - none
2487 * side effects - conf file for givenconf type is opened and read then parsed
2488 */
2489 static void
2490 parse_conf_file(int type, int cold)
2491 {
2492 FBFILE *file = NULL;
2493 const char *filename = get_conf_name(type);
2494
2495 if ((file = fbopen(filename, "r")) == NULL)
2496 {
2497 if (cold)
2498 ilog(L_ERROR, "Unable to read configuration file '%s': %s",
2499 filename, strerror(errno));
2500 else
2501 sendto_realops_flags(UMODE_ALL, L_ALL,
2502 "Unable to read configuration file '%s': %s",
2503 filename, strerror(errno));
2504 }
2505 else
2506 {
2507 parse_csv_file(file, type);
2508 fbclose(file);
2509 }
2510 }
2511
2512 /* clear_out_old_conf()
2513 *
2514 * inputs - none
2515 * output - none
2516 * side effects - Clear out the old configuration
2517 */
2518 static void
2519 clear_out_old_conf(void)
2520 {
2521 dlink_node *ptr = NULL, *next_ptr = NULL;
2522 struct ConfItem *conf;
2523 struct AccessItem *aconf;
2524 struct ClassItem *cltmp;
2525 struct MatchItem *match_item;
2526 dlink_list *free_items [] = {
2527 &server_items, &oconf_items, &hub_items, &leaf_items,
2528 &uconf_items, &xconf_items, &rxconf_items, &rkconf_items,
2529 &nresv_items, &cluster_items, &gdeny_items, NULL
2530 };
2531
2532 dlink_list ** iterator = free_items; /* C is dumb */
2533
2534 /* We only need to free anything allocated by yyparse() here.
2535 * Resetting structs, etc, is taken care of by set_default_conf().
2536 */
2537
2538 for (; *iterator != NULL; iterator++)
2539 {
2540 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2541 {
2542 conf = ptr->data;
2543 /* XXX This is less than pretty */
2544 if (conf->type == SERVER_TYPE)
2545 {
2546 aconf = map_to_conf(conf);
2547
2548 if (aconf->clients != 0)
2549 {
2550 SetConfIllegal(aconf);
2551 dlinkDelete(&conf->node, &server_items);
2552 }
2553 else
2554 {
2555 delete_conf_item(conf);
2556 }
2557 }
2558 else if (conf->type == OPER_TYPE)
2559 {
2560 aconf = map_to_conf(conf);
2561
2562 if (aconf->clients != 0)
2563 {
2564 SetConfIllegal(aconf);
2565 dlinkDelete(&conf->node, &oconf_items);
2566 }
2567 else
2568 {
2569 delete_conf_item(conf);
2570 }
2571 }
2572 else if (conf->type == CLIENT_TYPE)
2573 {
2574 aconf = map_to_conf(conf);
2575
2576 if (aconf->clients != 0)
2577 {
2578 SetConfIllegal(aconf);
2579 }
2580 else
2581 {
2582 delete_conf_item(conf);
2583 }
2584 }
2585 else if (conf->type == XLINE_TYPE ||
2586 conf->type == RXLINE_TYPE ||
2587 conf->type == RKLINE_TYPE)
2588 {
2589 /* temporary (r)xlines are also on
2590 * the (r)xconf items list */
2591 if (conf->flags & CONF_FLAGS_TEMPORARY)
2592 continue;
2593
2594 delete_conf_item(conf);
2595 }
2596 else
2597 {
2598 if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2599 {
2600 match_item = map_to_conf(conf);
2601 if (match_item->ref_count <= 0)
2602 delete_conf_item(conf);
2603 else
2604 {
2605 match_item->illegal = 1;
2606 dlinkDelete(&conf->node, *iterator);
2607 }
2608 }
2609 else
2610 delete_conf_item(conf);
2611 }
2612 }
2613 }
2614
2615 /*
2616 * don't delete the class table, rather mark all entries
2617 * for deletion. The table is cleaned up by check_class. - avalon
2618 */
2619 DLINK_FOREACH(ptr, class_items.head)
2620 {
2621 cltmp = map_to_conf(ptr->data);
2622
2623 if (ptr != class_items.tail) /* never mark the "default" class */
2624 cltmp->active = 0;
2625 }
2626
2627 clear_out_address_conf();
2628
2629 /* clean out module paths */
2630 mod_clear_paths();
2631
2632 /* clean out ServerInfo */
2633 MyFree(ServerInfo.description);
2634 ServerInfo.description = NULL;
2635 MyFree(ServerInfo.network_name);
2636 ServerInfo.network_name = NULL;
2637 MyFree(ServerInfo.network_desc);
2638 ServerInfo.network_desc = NULL;
2639 MyFree(ConfigFileEntry.egdpool_path);
2640 ConfigFileEntry.egdpool_path = NULL;
2641 #ifdef HAVE_LIBCRYPTO
2642 if (ServerInfo.rsa_private_key != NULL)
2643 {
2644 RSA_free(ServerInfo.rsa_private_key);
2645 ServerInfo.rsa_private_key = NULL;
2646 }
2647
2648 MyFree(ServerInfo.rsa_private_key_file);
2649 ServerInfo.rsa_private_key_file = NULL;
2650 #endif
2651
2652 /* clean out old resvs from the conf */
2653 clear_conf_resv();
2654
2655 /* clean out AdminInfo */
2656 MyFree(AdminInfo.name);
2657 AdminInfo.name = NULL;
2658 MyFree(AdminInfo.email);
2659 AdminInfo.email = NULL;
2660 MyFree(AdminInfo.description);
2661 AdminInfo.description = NULL;
2662
2663 /* operator{} and class{} blocks are freed above */
2664 /* clean out listeners */
2665 close_listeners();
2666
2667 /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2668 * exempt{} and gecos{} blocks are freed above too
2669 */
2670
2671 /* clean out general */
2672 MyFree(ConfigFileEntry.servlink_path);
2673 ConfigFileEntry.servlink_path = NULL;
2674 #ifdef HAVE_LIBCRYPTO
2675 ConfigFileEntry.default_cipher_preference = NULL;
2676 #endif /* HAVE_LIBCRYPTO */
2677 delete_isupport("INVEX");
2678 delete_isupport("EXCEPTS");
2679 }
2680
2681 /* flush_deleted_I_P()
2682 *
2683 * inputs - none
2684 * output - none
2685 * side effects - This function removes I/P conf items
2686 */
2687 static void
2688 flush_deleted_I_P(void)
2689 {
2690 dlink_node *ptr;
2691 dlink_node *next_ptr;
2692 struct ConfItem *conf;
2693 struct AccessItem *aconf;
2694 dlink_list * free_items [] = {
2695 &server_items, &oconf_items, NULL
2696 };
2697 dlink_list ** iterator = free_items; /* C is dumb */
2698
2699 /* flush out deleted I and P lines
2700 * although still in use.
2701 */
2702 for (; *iterator != NULL; iterator++)
2703 {
2704 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2705 {
2706 conf = ptr->data;
2707 aconf = (struct AccessItem *)map_to_conf(conf);
2708
2709 if (IsConfIllegal(aconf))
2710 {
2711 dlinkDelete(ptr, *iterator);
2712
2713 if (aconf->clients == 0)
2714 delete_conf_item(conf);
2715 }
2716 }
2717 }
2718 }
2719
2720 /* get_conf_name()
2721 *
2722 * inputs - type of conf file to return name of file for
2723 * output - pointer to filename for type of conf
2724 * side effects - none
2725 */
2726 const char *
2727 get_conf_name(ConfType type)
2728 {
2729 switch (type)
2730 {
2731 case CONF_TYPE:
2732 return ConfigFileEntry.configfile;
2733 break;
2734 case KLINE_TYPE:
2735 return ConfigFileEntry.klinefile;
2736 break;
2737 case RKLINE_TYPE:
2738 return ConfigFileEntry.rklinefile;
2739 break;
2740 case DLINE_TYPE:
2741 return ConfigFileEntry.dlinefile;
2742 break;
2743 case XLINE_TYPE:
2744 return ConfigFileEntry.xlinefile;
2745 break;
2746 case RXLINE_TYPE:
2747 return ConfigFileEntry.rxlinefile;
2748 break;
2749 case CRESV_TYPE:
2750 return ConfigFileEntry.cresvfile;
2751 break;
2752 case NRESV_TYPE:
2753 return ConfigFileEntry.nresvfile;
2754 break;
2755 case GLINE_TYPE:
2756 return ConfigFileEntry.glinefile;
2757 break;
2758
2759 default:
2760 return NULL; /* This should NEVER HAPPEN since we call this function
2761 only with the above values, this will cause us to core
2762 at some point if this happens so we know where it was */
2763 }
2764 }
2765
2766 #define BAD_PING (-1)
2767
2768 /* get_conf_ping()
2769 *
2770 * inputs - pointer to struct AccessItem
2771 * - pointer to a variable that receives ping warning time
2772 * output - ping frequency
2773 * side effects - NONE
2774 */
2775 static int
2776 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2777 {
2778 struct ClassItem *aclass;
2779 struct AccessItem *aconf;
2780
2781 if (conf != NULL)
2782 {
2783 aconf = (struct AccessItem *)map_to_conf(conf);
2784 if (aconf->class_ptr != NULL)
2785 {
2786 aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2787 *pingwarn = PingWarning(aclass);
2788 return PingFreq(aclass);
2789 }
2790 }
2791
2792 return BAD_PING;
2793 }
2794
2795 /* get_client_class()
2796 *
2797 * inputs - pointer to client struct
2798 * output - pointer to name of class
2799 * side effects - NONE
2800 */
2801 const char *
2802 get_client_class(struct Client *target_p)
2803 {
2804 dlink_node *ptr;
2805 struct ConfItem *conf;
2806 struct AccessItem *aconf;
2807
2808 if (target_p != NULL && !IsMe(target_p) &&
2809 target_p->localClient->confs.head != NULL)
2810 {
2811 DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2812 {
2813 conf = ptr->data;
2814
2815 if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2816 conf->type == OPER_TYPE)
2817 {
2818 aconf = (struct AccessItem *) map_to_conf(conf);
2819 if (aconf->class_ptr != NULL)
2820 return aconf->class_ptr->name;
2821 }
2822 }
2823 }
2824
2825 return "default";
2826 }
2827
2828 /* get_client_ping()
2829 *
2830 * inputs - pointer to client struct
2831 * - pointer to a variable that receives ping warning time
2832 * output - ping frequency
2833 * side effects - NONE
2834 */
2835 int
2836 get_client_ping(struct Client *target_p, int *pingwarn)
2837 {
2838 int ping;
2839 struct ConfItem *conf;
2840 dlink_node *nlink;
2841
2842 if (target_p->localClient->confs.head != NULL)
2843 DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2844 {
2845 conf = nlink->data;
2846
2847 if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2848 (conf->type == OPER_TYPE))
2849 {
2850 ping = get_conf_ping(conf, pingwarn);
2851 if (ping > 0)
2852 return ping;
2853 }
2854 }
2855
2856 *pingwarn = 0;
2857 return DEFAULT_PINGFREQUENCY;
2858 }
2859
2860 /* find_class()
2861 *
2862 * inputs - string name of class
2863 * output - corresponding Class pointer
2864 * side effects - NONE
2865 */
2866 struct ConfItem *
2867 find_class(const char *classname)
2868 {
2869 struct ConfItem *conf;
2870
2871 if ((conf = find_exact_name_conf(CLASS_TYPE, classname, NULL, NULL)) != NULL)
2872 return conf;
2873
2874 return class_default;
2875 }
2876
2877 /* check_class()
2878 *
2879 * inputs - NONE
2880 * output - NONE
2881 * side effects -
2882 */
2883 void
2884 check_class(void)
2885 {
2886 dlink_node *ptr = NULL, *next_ptr = NULL;
2887
2888 DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2889 {
2890 struct ClassItem *aclass = map_to_conf(ptr->data);
2891
2892 if (!aclass->active && !CurrUserCount(aclass))
2893 {
2894 destroy_cidr_class(aclass);
2895 delete_conf_item(ptr->data);
2896 }
2897 }
2898 }
2899
2900 /* init_class()
2901 *
2902 * inputs - NONE
2903 * output - NONE
2904 * side effects -
2905 */
2906 void
2907 init_class(void)
2908 {
2909 struct ClassItem *aclass;
2910
2911 class_default = make_conf_item(CLASS_TYPE);
2912
2913 aclass = map_to_conf(class_default);
2914 aclass->active = 1;
2915 DupString(class_default->name, "default");
2916 ConFreq(aclass) = DEFAULT_CONNECTFREQUENCY;
2917 PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
2918 MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
2919 MaxSendq(aclass) = DEFAULT_SENDQ;
2920
2921 client_check_cb = register_callback("check_client", check_client);
2922 }
2923
2924 /* get_sendq()
2925 *
2926 * inputs - pointer to client
2927 * output - sendq for this client as found from its class
2928 * side effects - NONE
2929 */
2930 unsigned int
2931 get_sendq(struct Client *client_p)
2932 {
2933 unsigned int sendq = DEFAULT_SENDQ;
2934 dlink_node *ptr;
2935 struct ConfItem *conf;
2936 struct ConfItem *class_conf;
2937 struct ClassItem *aclass;
2938 struct AccessItem *aconf;
2939
2940 if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2941 {
2942 DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2943 {
2944 conf = ptr->data;
2945 if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2946 || (conf->type == CLIENT_TYPE))
2947 {
2948 aconf = (struct AccessItem *)map_to_conf(conf);
2949 if ((class_conf = aconf->class_ptr) == NULL)
2950 continue;
2951 aclass = (struct ClassItem *)map_to_conf(class_conf);
2952 sendq = MaxSendq(aclass);
2953 return sendq;
2954 }
2955 }
2956 }
2957 /* XXX return a default?
2958 * if here, then there wasn't an attached conf with a sendq
2959 * that is very bad -Dianora
2960 */
2961 return DEFAULT_SENDQ;
2962 }
2963
2964 /* conf_add_class_to_conf()
2965 *
2966 * inputs - pointer to config item
2967 * output - NONE
2968 * side effects - Add a class pointer to a conf
2969 */
2970 void
2971 conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
2972 {
2973 struct AccessItem *aconf = map_to_conf(conf);
2974 struct ClassItem *class = NULL;
2975
2976 if (class_name == NULL)
2977 {
2978 aconf->class_ptr = class_default;
2979
2980 if (conf->type == CLIENT_TYPE)
2981 sendto_realops_flags(UMODE_ALL, L_ALL,
2982 "Warning *** Defaulting to default class for %s@%s",
2983 aconf->user, aconf->host);
2984 else
2985 sendto_realops_flags(UMODE_ALL, L_ALL,
2986 "Warning *** Defaulting to default class for %s",
2987 conf->name);
2988 }
2989 else
2990 aconf->class_ptr = find_class(class_name);
2991
2992 if (aconf->class_ptr)
2993 class = map_to_conf(aconf->class_ptr);
2994
2995 if (aconf->class_ptr == NULL || !class->active)
2996 {
2997 if (conf->type == CLIENT_TYPE)
2998 sendto_realops_flags(UMODE_ALL, L_ALL,
2999 "Warning *** Defaulting to default class for %s@%s",
3000 aconf->user, aconf->host);
3001 else
3002 sendto_realops_flags(UMODE_ALL, L_ALL,
3003 "Warning *** Defaulting to default class for %s",
3004 conf->name);
3005 aconf->class_ptr = class_default;
3006 }
3007 }
3008
3009 /* conf_add_server()
3010 *
3011 * inputs - pointer to config item
3012 * - pointer to link count already on this conf
3013 * output - NONE
3014 * side effects - Add a connect block
3015 */
3016 int
3017 conf_add_server(struct ConfItem *conf, const char *class_name)
3018 {
3019 struct AccessItem *aconf;
3020 struct split_nuh_item nuh;
3021 char conf_user[USERLEN + 1];
3022 char conf_host[HOSTLEN + 1];
3023
3024 aconf = map_to_conf(conf);
3025
3026 conf_add_class_to_conf(conf, class_name);
3027
3028 if (!aconf->host || !conf->name)
3029 {
3030 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
3031 ilog(L_WARN, "Bad connect block");
3032 return -1;
3033 }
3034
3035 if (EmptyString(aconf->passwd) && !IsConfCryptLink(aconf))
3036 {
3037 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
3038 conf->name);
3039 ilog(L_WARN, "Bad connect block, host %s", conf->name);
3040 return -1;
3041 }
3042
3043 nuh.nuhmask = aconf->host;
3044 nuh.nickptr = NULL;
3045 nuh.userptr = conf_user;
3046 nuh.hostptr = conf_host;
3047
3048 nuh.nicksize = 0;
3049 nuh.usersize = sizeof(conf_user);
3050 nuh.hostsize = sizeof(conf_host);
3051
3052 split_nuh(&nuh);
3053
3054 MyFree(aconf->host);
3055 aconf->host = NULL;
3056
3057 DupString(aconf->user, conf_user); /* somehow username checking for servers
3058 got lost in H6/7, will have to be re-added */
3059 DupString(aconf->host, conf_host);
3060
3061 lookup_confhost(conf);
3062
3063 return 0;
3064 }
3065
3066 /* yyerror()
3067 *
3068 * inputs - message from parser
3069 * output - NONE
3070 * side effects - message to opers and log file entry is made
3071 */
3072 void
3073 yyerror(const char *msg)
3074 {
3075 char newlinebuf[IRCD_BUFSIZE];
3076
3077 if (conf_parser_ctx.pass != 1)
3078 return;
3079
3080 strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
3081 sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
3082 conffilebuf, lineno + 1, msg, newlinebuf);
3083 ilog(L_WARN, "\"%s\", line %u: %s: %s",
3084 conffilebuf, lineno + 1, msg, newlinebuf);
3085 }
3086
3087 int
3088 conf_fbgets(char *lbuf, unsigned int max_size, FBFILE *fb)
3089 {
3090 if (fbgets(lbuf, max_size, fb) == NULL)
3091 return 0;
3092
3093 return strlen(lbuf);
3094 }
3095
3096 int
3097 conf_yy_fatal_error(const char *msg)
3098 {
3099 return 0;
3100 }
3101
3102 /*
3103 * valid_tkline()
3104 *
3105 * inputs - pointer to ascii string to check
3106 * - whether the specified time is in seconds or minutes
3107 * output - -1 not enough parameters
3108 * - 0 if not an integer number, else the number
3109 * side effects - none
3110 * Originally written by Dianora (Diane, db@db.net)
3111 */
3112 time_t
3113 valid_tkline(const char *p, int minutes)
3114 {
3115 time_t result = 0;
3116
3117 for (; *p; ++p)
3118 {
3119 if (!IsDigit(*p))
3120 return 0;
3121
3122 result *= 10;
3123 result += ((*p) & 0xF);
3124 }
3125
3126 /*
3127 * In the degenerate case where oper does a /quote kline 0 user@host :reason
3128 * i.e. they specifically use 0, I am going to return 1 instead
3129 * as a return value of non-zero is used to flag it as a temporary kline
3130 */
3131 if (result == 0)
3132 result = 1;
3133
3134 /*
3135 * If the incoming time is in seconds convert it to minutes for the purpose
3136 * of this calculation
3137 */
3138 if (!minutes)
3139 result = result / (time_t)60;
3140
3141 if (result > MAX_TDKLINE_TIME)
3142 result = MAX_TDKLINE_TIME;
3143
3144 result = result * (time_t)60; /* turn it into seconds */
3145
3146 return result;
3147 }
3148
3149 /* valid_wild_card()
3150 *
3151 * input - pointer to client
3152 * - int flag, 0 for no warning oper 1 for warning oper
3153 * - count of following varargs to check
3154 * output - 0 if not valid, 1 if valid
3155 * side effects - NOTICE is given to source_p if warn is 1
3156 */
3157 int
3158 valid_wild_card(struct Client *source_p, int warn, int count, ...)
3159 {
3160 char *p;
3161 char tmpch;
3162 int nonwild = 0;
3163 va_list args;
3164
3165 /*
3166 * Now we must check the user and host to make sure there
3167 * are at least NONWILDCHARS non-wildcard characters in
3168 * them, otherwise assume they are attempting to kline
3169 * *@* or some variant of that. This code will also catch
3170 * people attempting to kline *@*.tld, as long as NONWILDCHARS
3171 * is greater than 3. In that case, there are only 3 non-wild
3172 * characters (tld), so if NONWILDCHARS is 4, the kline will
3173 * be disallowed.
3174 * -wnder
3175 */
3176
3177 va_start(args, count);
3178
3179 while (count--)
3180 {
3181 p = va_arg(args, char *);
3182 if (p == NULL)
3183 continue;
3184
3185 while ((tmpch = *p++))
3186 {
3187 if (!IsKWildChar(tmpch))
3188 {
3189 /*
3190 * If we find enough non-wild characters, we can
3191 * break - no point in searching further.
3192 */
3193 if (++nonwild >= ConfigFileEntry.min_nonwildcard)
3194 return 1;
3195 }
3196 }
3197 }
3198
3199 if (warn)
3200 sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
3201 me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
3202 return 0;
3203 }
3204
3205 /* XXX should this go into a separate file ? -Dianora */
3206 /* parse_aline
3207 *
3208 * input - pointer to cmd name being used
3209 * - pointer to client using cmd
3210 * - parc parameter count
3211 * - parv[] list of parameters to parse
3212 * - parse_flags bit map of things to test
3213 * - pointer to user or string to parse into
3214 * - pointer to host or NULL to parse into if non NULL
3215 * - pointer to optional tkline time or NULL
3216 * - pointer to target_server to parse into if non NULL
3217 * - pointer to reason to parse into
3218 *
3219 * output - 1 if valid, -1 if not valid
3220 * side effects - A generalised k/d/x etc. line parser,
3221 * "ALINE [time] user@host|string [ON] target :reason"
3222 * will parse returning a parsed user, host if
3223 * h_p pointer is non NULL, string otherwise.
3224 * if tkline_time pointer is non NULL a tk line will be set
3225 * to non zero if found.
3226 * if tkline_time pointer is NULL and tk line is found,
3227 * error is reported.
3228 * if target_server is NULL and an "ON" is found error
3229 * is reported.
3230 * if reason pointer is NULL ignore pointer,
3231 * this allows use of parse_a_line in unkline etc.
3232 *
3233 * - Dianora
3234 */
3235 int
3236 parse_aline(const char *cmd, struct Client *source_p,
3237 int parc, char **parv,
3238 int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
3239 char **target_server, char **reason)
3240 {
3241 int found_tkline_time=0;
3242 static char def_reason[] = "No Reason";
3243 static char user[USERLEN*4+1];
3244 static char host[HOSTLEN*4+1];
3245
3246 parv++;
3247 parc--;
3248
3249 found_tkline_time = valid_tkline(*parv, TK_MINUTES);
3250
3251 if (found_tkline_time != 0)
3252 {
3253 parv++;
3254 parc--;
3255
3256 if (tkline_time != NULL)
3257 *tkline_time = found_tkline_time;
3258 else
3259 {
3260 sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3261 me.name, source_p->name, cmd);
3262 return -1;
3263 }
3264 }
3265
3266 if (parc == 0)
3267 {
3268 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3269 me.name, source_p->name, cmd);
3270 return -1;
3271 }
3272
3273 if (h_p == NULL)
3274 *up_p = *parv;
3275 else
3276 {
3277 if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
3278 return -1;
3279
3280 *up_p = user;
3281 *h_p = host;
3282 }
3283
3284 parc--;
3285 parv++;
3286
3287 if (parc != 0)
3288 {
3289 if (irccmp(*parv, "ON") == 0)
3290 {
3291 parc--;
3292 parv++;
3293
3294 if (target_server == NULL)
3295 {
3296 sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
3297 me.name, source_p->name, cmd);
3298 return -1;
3299 }
3300
3301 if (!IsOperRemoteBan(source_p))
3302 {
3303 sendto_one(source_p, form_str(ERR_NOPRIVS),
3304 me.name, source_p->name, "remoteban");
3305 return -1;
3306 }
3307
3308 if (parc == 0 || EmptyString(*parv))
3309 {
3310 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3311 me.name, source_p->name, cmd);
3312 return -1;
3313 }
3314
3315 *target_server = *parv;
3316 parc--;
3317 parv++;
3318 }
3319 else
3320 {
3321 /* Make sure target_server *is* NULL if no ON server found
3322 * caller probably NULL'd it first, but no harm to do it again -db
3323 */
3324 if (target_server != NULL)
3325 *target_server = NULL;
3326 }
3327 }
3328
3329 if (h_p != NULL)
3330 {
3331 if (strchr(user, '!') != NULL)
3332 {
3333 sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3334 me.name, source_p->name);
3335 return -1;
3336 }
3337
3338 if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 2, *up_p, *h_p))
3339 return -1;
3340 }
3341 else
3342 if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 1, *up_p))
3343 return -1;
3344
3345 if (reason != NULL)
3346 {
3347 if (parc != 0 && !EmptyString(*parv))
3348 {
3349 *reason = *parv;
3350 if (!valid_comment(source_p, *reason, YES))
3351 return -1;
3352 }
3353 else
3354 *reason = def_reason;
3355 }
3356
3357 return 1;
3358 }
3359
3360 /* find_user_host()
3361 *
3362 * inputs - pointer to client placing kline
3363 * - pointer to user_host_or_nick
3364 * - pointer to user buffer
3365 * - pointer to host buffer
3366 * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
3367 * side effects -
3368 */
3369 static int
3370 find_user_host(struct Client *source_p, char *user_host_or_nick,
3371 char *luser, char *lhost, unsigned int flags)
3372 {
3373 struct Client *target_p = NULL;
3374 char *hostp = NULL;
3375
3376 if (lhost == NULL)
3377 {
3378 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
3379 return 1;
3380 }
3381
3382 if ((hostp = strchr(user_host_or_nick, '@')) || *user_host_or_nick == '*')
3383 {
3384 /* Explicit user@host mask given */
3385
3386 if (hostp != NULL) /* I'm a little user@host */
3387 {
3388 *(hostp++) = '\0'; /* short and squat */
3389 if (*user_host_or_nick)
3390 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
3391 else
3392 strcpy(luser, "*");
3393 if (*hostp)
3394 strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
3395 else
3396 strcpy(lhost, "*");
3397 }
3398 else
3399 {
3400 luser[0] = '*'; /* no @ found, assume its *@somehost */
3401 luser[1] = '\0';
3402 strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
3403 }
3404
3405 return 1;
3406 }
3407 else if (!(flags & NOUSERLOOKUP))
3408 {
3409 /* Try to find user@host mask from nick */
3410 /* Okay to use source_p as the first param, because source_p == client_p */
3411 if ((target_p =
3412 find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
3413 return 0;
3414
3415 if (IsExemptKline(target_p))
3416 {
3417 if (!IsServer(source_p))
3418 sendto_one(source_p,
3419 ":%s NOTICE %s :%s is E-lined",
3420 me.name, source_p->name, target_p->name);
3421 return 0;
3422 }
3423
3424 /*
3425 * turn the "user" bit into "*user", blow away '~'
3426 * if found in original user name (non-idented)
3427 */
3428 strlcpy(luser, target_p->username, USERLEN*4 + 1);
3429
3430 if (target_p->username[0] == '~')
3431 luser[0] = '*';
3432
3433 if (target_p->sockhost[0] == '\0' ||
3434 (target_p->sockhost[0] == '0' && target_p->sockhost[1] == '\0'))
3435 strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
3436 else
3437 strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
3438 return 1;
3439 }
3440
3441 return 0;
3442 }
3443
3444 /* valid_comment()
3445 *
3446 * inputs - pointer to client
3447 * - pointer to comment
3448 * output - 0 if no valid comment,
3449 * - 1 if valid
3450 * side effects - truncates reason where necessary
3451 */
3452 int
3453 valid_comment(struct Client *source_p, char *comment, int warn)
3454 {
3455 if (strchr(comment, '"'))
3456 {
3457 if (warn)
3458 sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3459 me.name, source_p->name);
3460 return 0;
3461 }
3462
3463 if (strlen(comment) > REASONLEN)
3464 comment[REASONLEN-1] = '\0';
3465
3466 return 1;
3467 }
3468
3469 /* match_conf_password()
3470 *
3471 * inputs - pointer to given password
3472 * - pointer to Conf
3473 * output - 1 or 0 if match
3474 * side effects - none
3475 */
3476 int
3477 match_conf_password(const char *password, const struct AccessItem *aconf)
3478 {
3479 const char *encr = NULL;
3480
3481 if (password == NULL || aconf->passwd == NULL)
3482 return 0;
3483
3484 if (aconf->flags & CONF_FLAGS_ENCRYPTED)
3485 {
3486 /* use first two chars of the password they send in as salt */
3487 /* If the password in the conf is MD5, and ircd is linked
3488 * to scrypt on FreeBSD, or the standard crypt library on
3489 * glibc Linux, then this code will work fine on generating
3490 * the proper encrypted hash for comparison.
3491 */
3492 if (*aconf->passwd)
3493 encr = crypt(password, aconf->passwd);
3494 else
3495 encr = "";
3496 }
3497 else
3498 encr = password;
3499
3500 return !strcmp(encr, aconf->passwd);
3501 }
3502
3503 /*
3504 * cluster_a_line
3505 *
3506 * inputs - client sending the cluster
3507 * - command name "KLINE" "XLINE" etc.
3508 * - capab -- CAP_KLN etc. from s_serv.h
3509 * - cluster type -- CLUSTER_KLINE etc. from s_conf.h
3510 * - pattern and args to send along
3511 * output - none
3512 * side effects - Take source_p send the pattern with args given
3513 * along to all servers that match capab and cluster type
3514 */
3515 void
3516 cluster_a_line(struct Client *source_p, const char *command,
3517 int capab, int cluster_type, const char *pattern, ...)
3518 {
3519 va_list args;
3520 char buffer[IRCD_BUFSIZE];
3521 const dlink_node *ptr = NULL;
3522
3523 va_start(args, pattern);
3524 vsnprintf(buffer, sizeof(buffer), pattern, args);
3525 va_end(args);
3526
3527 DLINK_FOREACH(ptr, cluster_items.head)
3528 {
3529 const struct ConfItem *conf = ptr->data;
3530
3531 if (conf->flags & cluster_type)
3532 sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
3533 "%s %s %s", command, conf->name, buffer);
3534 }
3535 }
3536
3537 /*
3538 * split_nuh
3539 *
3540 * inputs - pointer to original mask (modified in place)
3541 * - pointer to pointer where nick should go
3542 * - pointer to pointer where user should go
3543 * - pointer to pointer where host should go
3544 * output - NONE
3545 * side effects - mask is modified in place
3546 * If nick pointer is NULL, ignore writing to it
3547 * this allows us to use this function elsewhere.
3548 *
3549 * mask nick user host
3550 * ---------------------- ------- ------- ------
3551 * Dianora!db@db.net Dianora db db.net
3552 * Dianora Dianora * *
3553 * db.net * * db.net
3554 * OR if nick pointer is NULL
3555 * Dianora - * Dianora
3556 * Dianora! Dianora * *
3557 * Dianora!@ Dianora * *
3558 * Dianora!db Dianora db *
3559 * Dianora!@db.net Dianora * db.net
3560 * db@db.net * db db.net
3561 * !@ * * *
3562 * @ * * *
3563 * ! * * *
3564 */
3565 void
3566 split_nuh(struct split_nuh_item *const iptr)
3567 {
3568 char *p = NULL, *q = NULL;
3569
3570 if (iptr->nickptr)
3571 strlcpy(iptr->nickptr, "*", iptr->nicksize);
3572 if (iptr->userptr)
3573 strlcpy(iptr->userptr, "*", iptr->usersize);
3574 if (iptr->hostptr)
3575 strlcpy(iptr->hostptr, "*", iptr->hostsize);
3576
3577 if ((p = strchr(iptr->nuhmask, '!')))
3578 {
3579 *p = '\0';
3580
3581 if (iptr->nickptr && *iptr->nuhmask != '\0')
3582 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3583
3584 if ((q = strchr(++p, '@'))) {
3585 *q++ = '\0';
3586
3587 if (*p != '\0')
3588 strlcpy(iptr->userptr, p, iptr->usersize);
3589
3590 if (*q != '\0')
3591 strlcpy(iptr->hostptr, q, iptr->hostsize);
3592 }
3593 else
3594 {
3595 if (*p != '\0')
3596 strlcpy(iptr->userptr, p, iptr->usersize);
3597 }
3598 }
3599 else
3600 {
3601 /* No ! found so lets look for a user@host */
3602 if ((p = strchr(iptr->nuhmask, '@')))
3603 {
3604 /* if found a @ */
3605 *p++ = '\0';
3606
3607 if (*iptr->nuhmask != '\0')
3608 strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
3609
3610 if (*p != '\0')
3611 strlcpy(iptr->hostptr, p, iptr->hostsize);
3612 }
3613 else
3614 {
3615 /* no @ found */
3616 if (!iptr->nickptr || strpbrk(iptr->nuhmask, ".:"))
3617 strlcpy(iptr->hostptr, iptr->nuhmask, iptr->hostsize);
3618 else
3619 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3620 }
3621 }
3622 }
3623
3624 /*
3625 * flags_to_ascii
3626 *
3627 * inputs - flags is a bitmask
3628 * - pointer to table of ascii letters corresponding
3629 * to each bit
3630 * - flag 1 for convert ToLower if bit missing
3631 * 0 if ignore.
3632 * output - none
3633 * side effects - string pointed to by p has bitmap chars written to it
3634 */
3635 static void
3636 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3637 int lowerit)
3638 {
3639 unsigned int mask = 1;
3640 int i = 0;
3641
3642 for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3643 {
3644 if (flags & mask)
3645 *p++ = bit_table[i];
3646 else if (lowerit)
3647 *p++ = ToLower(bit_table[i]);
3648 }
3649 *p = '\0';
3650 }
3651
3652 /*
3653 * cidr_limit_reached
3654 *
3655 * inputs - int flag allowing over_rule of limits
3656 * - pointer to the ip to be added
3657 * - pointer to the class
3658 * output - non zero if limit reached
3659 * 0 if limit not reached
3660 * side effects -
3661 */
3662 static int
3663 cidr_limit_reached(int over_rule,
3664 struct irc_ssaddr *ip, struct ClassItem *aclass)
3665 {
3666 dlink_node *ptr = NULL;
3667 struct CidrItem *cidr;
3668
3669 if (NumberPerCidr(aclass) <= 0)
3670 return 0;
3671
3672 if (ip->ss.ss_family == AF_INET)
3673 {
3674 if (CidrBitlenIPV4(aclass) <= 0)
3675 return 0;
3676
3677 DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3678 {
3679 cidr = ptr->data;
3680 if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3681 {
3682 if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3683 return -1;
3684 cidr->number_on_this_cidr++;
3685 return 0;
3686 }
3687 }
3688 cidr = MyMalloc(sizeof(struct CidrItem));
3689 cidr->number_on_this_cidr = 1;
3690 cidr->mask = *ip;
3691 mask_addr(&cidr->mask, CidrBitlenIPV4(aclass));
3692 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3693 }
3694 #ifdef IPV6
3695 else if (CidrBitlenIPV6(aclass) > 0)
3696 {
3697 DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3698 {
3699 cidr = ptr->data;
3700 if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3701 {
3702 if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3703 return -1;
3704 cidr->number_on_this_cidr++;
3705 return 0;
3706 }
3707 }
3708 cidr = MyMalloc(sizeof(struct CidrItem));
3709 cidr->number_on_this_cidr = 1;
3710 cidr->mask = *ip;
3711 mask_addr(&cidr->mask, CidrBitlenIPV6(aclass));
3712 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3713 }
3714 #endif
3715 return 0;
3716 }
3717
3718 /*
3719 * remove_from_cidr_check
3720 *
3721 * inputs - pointer to the ip to be removed
3722 * - pointer to the class
3723 * output - NONE
3724 * side effects -
3725 */
3726 static void
3727 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3728 {
3729 dlink_node *ptr = NULL;
3730 dlink_node *next_ptr = NULL;
3731 struct CidrItem *cidr;
3732
3733 if (NumberPerCidr(aclass) == 0)
3734 return;
3735
3736 if (ip->ss.ss_family == AF_INET)
3737 {
3738 if (CidrBitlenIPV4(aclass) <= 0)
3739 return;
3740
3741 DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3742 {
3743 cidr = ptr->data;
3744 if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3745 {
3746 cidr->number_on_this_cidr--;
3747 if (cidr->number_on_this_cidr == 0)
3748 {
3749 dlinkDelete(ptr, &aclass->list_ipv4);
3750 MyFree(cidr);
3751 return;
3752 }
3753 }
3754 }
3755 }
3756 #ifdef IPV6
3757 else if (CidrBitlenIPV6(aclass) > 0)
3758 {
3759 DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3760 {
3761 cidr = ptr->data;
3762 if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3763 {
3764 cidr->number_on_this_cidr--;
3765 if (cidr->number_on_this_cidr == 0)
3766 {
3767 dlinkDelete(ptr, &aclass->list_ipv6);
3768 MyFree(cidr);
3769 return;
3770 }
3771 }
3772 }
3773 }
3774 #endif
3775 }
3776
3777 static void
3778 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3779 dlink_list *old_list, dlink_list *new_list, int changed)
3780 {
3781 dlink_node *ptr;
3782 struct Client *client_p;
3783 struct ConfItem *conf;
3784 struct AccessItem *aconf;
3785
3786 if (!changed)
3787 {
3788 *new_list = *old_list;
3789 old_list->head = old_list->tail = NULL;
3790 old_list->length = 0;
3791 return;
3792 }
3793
3794 DLINK_FOREACH(ptr, local_client_list.head)
3795 {
3796 client_p = ptr->data;
3797 if (client_p->localClient->aftype != aftype)
3798 continue;
3799 if (dlink_list_length(&client_p->localClient->confs) == 0)
3800 continue;
3801
3802 conf = client_p->localClient->confs.tail->data;
3803 if (conf->type == CLIENT_TYPE)
3804 {
3805 aconf = map_to_conf(conf);
3806 if (aconf->class_ptr == oldcl)
3807 cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3808 }
3809 }
3810 }
3811
3812 /*
3813 * rebuild_cidr_class
3814 *
3815 * inputs - pointer to old conf
3816 * - pointer to new_class
3817 * output - none
3818 * side effects - rebuilds the class link list of cidr blocks
3819 */
3820 void
3821 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3822 {
3823 struct ClassItem *old_class = map_to_conf(conf);
3824
3825 if (NumberPerCidr(old_class) > 0 && NumberPerCidr(new_class) > 0)
3826 {
3827 if (CidrBitlenIPV4(old_class) > 0 && CidrBitlenIPV4(new_class) > 0)
3828 rebuild_cidr_list(AF_INET, conf, new_class,
3829 &old_class->list_ipv4, &new_class->list_ipv4,
3830 CidrBitlenIPV4(old_class) != CidrBitlenIPV4(new_class));
3831
3832 #ifdef IPV6
3833 if (CidrBitlenIPV6(old_class) > 0 && CidrBitlenIPV6(new_class) > 0)
3834 rebuild_cidr_list(AF_INET6, conf, new_class,
3835 &old_class->list_ipv6, &new_class->list_ipv6,
3836 CidrBitlenIPV6(old_class) != CidrBitlenIPV6(new_class));
3837 #endif
3838 }
3839
3840 destroy_cidr_class(old_class);
3841 }
3842
3843 /*
3844 * destroy_cidr_list
3845 *
3846 * inputs - pointer to class dlink list of cidr blocks
3847 * output - none
3848 * side effects - completely destroys the class link list of cidr blocks
3849 */
3850 static void
3851 destroy_cidr_list(dlink_list *list)
3852 {
3853 dlink_node *ptr = NULL, *next_ptr = NULL;
3854
3855 DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3856 {
3857 dlinkDelete(ptr, list);
3858 MyFree(ptr->data);
3859 }
3860 }
3861
3862 /*
3863 * destroy_cidr_class
3864 *
3865 * inputs - pointer to class
3866 * output - none
3867 * side effects - completely destroys the class link list of cidr blocks
3868 */
3869 static void
3870 destroy_cidr_class(struct ClassItem *aclass)
3871 {
3872 destroy_cidr_list(&aclass->list_ipv4);
3873 destroy_cidr_list(&aclass->list_ipv6);
3874 }

Properties

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