ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/s_conf.c
Revision: 867
Committed: Thu May 17 14:59:27 2007 UTC (16 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 100752 byte(s)
Log Message:
- Fixed occasional core when placing RESVs on channel names as repoared
  by Christopher A. Bongaarts.


File Contents

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

Properties

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