ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/s_conf.c
Revision: 618
Committed: Tue May 23 07:07:53 2006 UTC (17 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 101401 byte(s)
Log Message:
- attach_conf():  We even need to increment CurrUserCount if a class got
  attached to a server or operator.  Spotted by stu.
- Removed IRCD_SOCKET_ERROR define

File Contents

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

Properties

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