ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 876
Committed: Wed Oct 24 21:51:21 2007 UTC (17 years, 10 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 100887 byte(s)
Log Message:
Backported WATCH

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

Properties

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