ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1325
Committed: Sat Mar 31 10:29:02 2012 UTC (11 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 99866 byte(s)
Log Message:
- Get rid of fileio.c. Replace some ircsprintf() with snprintf() while on it

File Contents

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

Properties

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