]> jfr.im git - solanum.git/blame - ircd/s_newconf.c
authd/providers/ident: fix up trailing lf/cr at end of username
[solanum.git] / ircd / s_newconf.c
CommitLineData
212380e3
AC
1/*
2 * ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
3 * s_newconf.c - code for dealing with conf stuff
4 *
5 * Copyright (C) 2004 Lee Hardy <lee@leeh.co.uk>
6 * Copyright (C) 2004-2005 ircd-ratbox development team
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * 1.Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * 2.Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3.The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
212380e3
AC
31 */
32
33#include "stdinc.h"
34#include "ircd_defs.h"
212380e3
AC
35#include "s_conf.h"
36#include "s_newconf.h"
212380e3 37#include "client.h"
212380e3
AC
38#include "s_serv.h"
39#include "send.h"
40#include "hostmask.h"
41#include "newconf.h"
42#include "hash.h"
a4bf26dd
EM
43#include "rb_dictionary.h"
44#include "rb_radixtree.h"
77d3d2db
KB
45#include "s_assert.h"
46#include "logger.h"
1d02144f 47#include "dns.h"
212380e3 48
330fc5c1
AC
49rb_dlink_list shared_conf_list;
50rb_dlink_list cluster_conf_list;
51rb_dlink_list oper_conf_list;
52rb_dlink_list hubleaf_conf_list;
53rb_dlink_list server_conf_list;
54rb_dlink_list xline_conf_list;
55rb_dlink_list resv_conf_list; /* nicks only! */
56rb_dlink_list nd_list; /* nick delay */
57rb_dlink_list tgchange_list;
212380e3 58
7018b86a 59rb_patricia_tree_t *tgchange_tree;
212380e3 60
398b6a73 61static rb_bh *nd_heap = NULL;
212380e3
AC
62
63static void expire_temp_rxlines(void *unused);
64static void expire_nd_entries(void *unused);
65
e410dcf5
AC
66struct ev_entry *expire_nd_entries_ev = NULL;
67struct ev_entry *expire_temp_rxlines_ev = NULL;
68
212380e3
AC
69void
70init_s_newconf(void)
71{
e410dcf5
AC
72 tgchange_tree = rb_new_patricia(PATRICIA_BITS);
73 nd_heap = rb_bh_create(sizeof(struct nd_entry), ND_HEAP_SIZE, "nd_heap");
74 expire_nd_entries_ev = rb_event_addish("expire_nd_entries", expire_nd_entries, NULL, 30);
75 expire_temp_rxlines_ev = rb_event_addish("expire_temp_rxlines", expire_temp_rxlines, NULL, 60);
212380e3
AC
76}
77
78void
79clear_s_newconf(void)
80{
81 struct server_conf *server_p;
330fc5c1 82 rb_dlink_node *ptr;
637c4932 83 rb_dlink_node *next_ptr;
212380e3 84
637c4932 85 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, shared_conf_list.head)
212380e3
AC
86 {
87 /* ptr here is ptr->data->node */
330fc5c1 88 rb_dlinkDelete(ptr, &shared_conf_list);
212380e3
AC
89 free_remote_conf(ptr->data);
90 }
91
637c4932 92 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, cluster_conf_list.head)
212380e3 93 {
330fc5c1 94 rb_dlinkDelete(ptr, &cluster_conf_list);
212380e3
AC
95 free_remote_conf(ptr->data);
96 }
97
637c4932 98 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, hubleaf_conf_list.head)
212380e3 99 {
330fc5c1 100 rb_dlinkDelete(ptr, &hubleaf_conf_list);
212380e3
AC
101 free_remote_conf(ptr->data);
102 }
103
637c4932 104 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, oper_conf_list.head)
212380e3
AC
105 {
106 free_oper_conf(ptr->data);
330fc5c1 107 rb_dlinkDestroy(ptr, &oper_conf_list);
212380e3
AC
108 }
109
637c4932 110 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, server_conf_list.head)
212380e3
AC
111 {
112 server_p = ptr->data;
113
114 if(!server_p->servers)
115 {
330fc5c1 116 rb_dlinkDelete(ptr, &server_conf_list);
212380e3
AC
117 free_server_conf(ptr->data);
118 }
119 else
120 server_p->flags |= SERVER_ILLEGAL;
121 }
122}
123
124void
125clear_s_newconf_bans(void)
126{
127 struct ConfItem *aconf;
637c4932 128 rb_dlink_node *ptr, *next_ptr;
212380e3 129
637c4932 130 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, xline_conf_list.head)
212380e3
AC
131 {
132 aconf = ptr->data;
133
134 if(aconf->hold)
135 continue;
136
137 free_conf(aconf);
330fc5c1 138 rb_dlinkDestroy(ptr, &xline_conf_list);
212380e3
AC
139 }
140
637c4932 141 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, resv_conf_list.head)
212380e3
AC
142 {
143 aconf = ptr->data;
144
145 /* temporary resv */
146 if(aconf->hold)
147 continue;
148
149 free_conf(aconf);
330fc5c1 150 rb_dlinkDestroy(ptr, &resv_conf_list);
212380e3
AC
151 }
152
153 clear_resv_hash();
154}
155
156struct remote_conf *
157make_remote_conf(void)
158{
eddc2ab6 159 struct remote_conf *remote_p = rb_malloc(sizeof(struct remote_conf));
212380e3
AC
160 return remote_p;
161}
162
163void
164free_remote_conf(struct remote_conf *remote_p)
165{
166 s_assert(remote_p != NULL);
167 if(remote_p == NULL)
168 return;
169
637c4932
VY
170 rb_free(remote_p->username);
171 rb_free(remote_p->host);
172 rb_free(remote_p->server);
173 rb_free(remote_p);
212380e3
AC
174}
175
bd43a444 176bool
55abcbb2 177find_shared_conf(const char *username, const char *host,
212380e3
AC
178 const char *server, int flags)
179{
180 struct remote_conf *shared_p;
330fc5c1 181 rb_dlink_node *ptr;
212380e3 182
5cefa1d6 183 RB_DLINK_FOREACH(ptr, shared_conf_list.head)
212380e3
AC
184 {
185 shared_p = ptr->data;
186
187 if(match(shared_p->username, username) &&
188 match(shared_p->host, host) &&
189 match(shared_p->server, server))
190 {
191 if(shared_p->flags & flags)
bd43a444 192 return true;
212380e3 193 else
bd43a444 194 return false;
212380e3
AC
195 }
196 }
197
ab31d2b0 198 return false;
212380e3
AC
199}
200
201void
202propagate_generic(struct Client *source_p, const char *command,
203 const char *target, int cap, const char *format, ...)
204{
205 char buffer[BUFSIZE];
206 va_list args;
207
208 va_start(args, format);
5203cba5 209 vsnprintf(buffer, sizeof(buffer), format, args);
212380e3
AC
210 va_end(args);
211
212 sendto_match_servs(source_p, target, cap, NOCAPS,
213 "%s %s %s",
214 command, target, buffer);
215 sendto_match_servs(source_p, target, CAP_ENCAP, cap,
216 "ENCAP %s %s %s",
217 target, command, buffer);
218}
55abcbb2 219
212380e3
AC
220void
221cluster_generic(struct Client *source_p, const char *command,
222 int cltype, int cap, const char *format, ...)
223{
224 char buffer[BUFSIZE];
225 struct remote_conf *shared_p;
226 va_list args;
330fc5c1 227 rb_dlink_node *ptr;
212380e3
AC
228
229 va_start(args, format);
5203cba5 230 vsnprintf(buffer, sizeof(buffer), format, args);
212380e3
AC
231 va_end(args);
232
5cefa1d6 233 RB_DLINK_FOREACH(ptr, cluster_conf_list.head)
212380e3
AC
234 {
235 shared_p = ptr->data;
236
237 if(!(shared_p->flags & cltype))
238 continue;
239
240 sendto_match_servs(source_p, shared_p->server, cap, NOCAPS,
241 "%s %s %s",
242 command, shared_p->server, buffer);
243 sendto_match_servs(source_p, shared_p->server, CAP_ENCAP, cap,
244 "ENCAP %s %s %s",
245 shared_p->server, command, buffer);
246 }
247}
248
249struct oper_conf *
250make_oper_conf(void)
251{
eddc2ab6 252 struct oper_conf *oper_p = rb_malloc(sizeof(struct oper_conf));
212380e3
AC
253 return oper_p;
254}
255
256void
257free_oper_conf(struct oper_conf *oper_p)
258{
259 s_assert(oper_p != NULL);
260 if(oper_p == NULL)
261 return;
262
637c4932
VY
263 rb_free(oper_p->username);
264 rb_free(oper_p->host);
265 rb_free(oper_p->name);
462ae9d7 266 rb_free(oper_p->certfp);
212380e3
AC
267
268 if(oper_p->passwd)
269 {
270 memset(oper_p->passwd, 0, strlen(oper_p->passwd));
637c4932 271 rb_free(oper_p->passwd);
212380e3
AC
272 }
273
274#ifdef HAVE_LIBCRYPTO
637c4932 275 rb_free(oper_p->rsa_pubkey_file);
212380e3
AC
276
277 if(oper_p->rsa_pubkey)
278 RSA_free(oper_p->rsa_pubkey);
279#endif
280
637c4932 281 rb_free(oper_p);
212380e3
AC
282}
283
284struct oper_conf *
285find_oper_conf(const char *username, const char *host, const char *locip, const char *name)
286{
287 struct oper_conf *oper_p;
e7046ee5 288 struct rb_sockaddr_storage ip, cip;
212380e3
AC
289 char addr[HOSTLEN+1];
290 int bits, cbits;
330fc5c1 291 rb_dlink_node *ptr;
212380e3 292
29c92cf9 293 parse_netmask(locip, &cip, &cbits);
212380e3 294
5cefa1d6 295 RB_DLINK_FOREACH(ptr, oper_conf_list.head)
212380e3
AC
296 {
297 oper_p = ptr->data;
298
299 /* name/username doesnt match.. */
300 if(irccmp(oper_p->name, name) || !match(oper_p->username, username))
301 continue;
302
f427c8b0 303 rb_strlcpy(addr, oper_p->host, sizeof(addr));
212380e3 304
29c92cf9 305 if(parse_netmask(addr, &ip, &bits) != HM_HOST)
212380e3 306 {
e867208d 307 if(GET_SS_FAMILY(&ip) == GET_SS_FAMILY(&cip) &&
212380e3
AC
308 comp_with_mask_sock((struct sockaddr *)&ip, (struct sockaddr *)&cip, bits))
309 return oper_p;
310 }
311
312 /* we have to compare against the host as well, because its
313 * valid to set a spoof to an IP, which if we only compare
314 * in ip form to sockhost will not necessarily match --anfl
315 */
316 if(match(oper_p->host, host))
317 return oper_p;
318 }
319
320 return NULL;
321}
322
212380e3
AC
323struct server_conf *
324make_server_conf(void)
325{
eddc2ab6 326 struct server_conf *server_p = rb_malloc(sizeof(struct server_conf));
212380e3
AC
327 server_p->aftype = AF_INET;
328 return server_p;
329}
330
331void
332free_server_conf(struct server_conf *server_p)
333{
334 s_assert(server_p != NULL);
335 if(server_p == NULL)
336 return;
337
338 if(!EmptyString(server_p->passwd))
339 {
340 memset(server_p->passwd, 0, strlen(server_p->passwd));
637c4932 341 rb_free(server_p->passwd);
212380e3
AC
342 }
343
344 if(!EmptyString(server_p->spasswd))
345 {
346 memset(server_p->spasswd, 0, strlen(server_p->spasswd));
637c4932 347 rb_free(server_p->spasswd);
212380e3
AC
348 }
349
637c4932
VY
350 rb_free(server_p->name);
351 rb_free(server_p->host);
352 rb_free(server_p->class_name);
353 rb_free(server_p);
212380e3
AC
354}
355
1d02144f
AC
356/*
357 * conf_dns_callback
358 * inputs - pointer to struct ConfItem
359 * - pointer to adns reply
360 * output - none
361 * side effects - called when resolver query finishes
362 * if the query resulted in a successful search, hp will contain
363 * a non-null pointer, otherwise hp will be null.
364 * if successful save hp in the conf item it was called with
365 */
366static void
367conf_dns_callback(const char *result, int status, int aftype, void *data)
368{
369 struct server_conf *server_p = data;
370
371 if(status == 1)
372 rb_inet_pton_sock(result, (struct sockaddr *)&server_p->my_ipnum);
373
374 server_p->dns_query = 0;
375}
376
212380e3
AC
377void
378add_server_conf(struct server_conf *server_p)
379{
380 if(EmptyString(server_p->class_name))
381 {
47a03750 382 server_p->class_name = rb_strdup("default");
212380e3
AC
383 server_p->class = default_class;
384 return;
385 }
386
387 server_p->class = find_class(server_p->class_name);
388
389 if(server_p->class == default_class)
390 {
391 conf_report_error("Warning connect::class invalid for %s",
392 server_p->name);
393
637c4932 394 rb_free(server_p->class_name);
47a03750 395 server_p->class_name = rb_strdup("default");
212380e3
AC
396 }
397
1d02144f 398 if(strpbrk(server_p->host, "*?"))
212380e3 399 return;
1d02144f
AC
400
401 server_p->dns_query =
402 lookup_hostname(server_p->host, GET_SS_FAMILY(&server_p->my_ipnum), conf_dns_callback, server_p);
212380e3
AC
403}
404
405struct server_conf *
406find_server_conf(const char *name)
407{
408 struct server_conf *server_p;
330fc5c1 409 rb_dlink_node *ptr;
212380e3 410
5cefa1d6 411 RB_DLINK_FOREACH(ptr, server_conf_list.head)
212380e3
AC
412 {
413 server_p = ptr->data;
414
415 if(ServerConfIllegal(server_p))
416 continue;
417
418 if(match(name, server_p->name))
419 return server_p;
420 }
421
422 return NULL;
423}
424
425void
426attach_server_conf(struct Client *client_p, struct server_conf *server_p)
427{
428 /* already have an attached conf */
429 if(client_p->localClient->att_sconf)
430 {
431 /* short circuit this special case :) */
432 if(client_p->localClient->att_sconf == server_p)
433 return;
434
435 detach_server_conf(client_p);
436 }
437
438 CurrUsers(server_p->class)++;
439
440 client_p->localClient->att_sconf = server_p;
441 server_p->servers++;
442}
443
444void
445detach_server_conf(struct Client *client_p)
446{
447 struct server_conf *server_p = client_p->localClient->att_sconf;
448
449 if(server_p == NULL)
450 return;
451
452 client_p->localClient->att_sconf = NULL;
453 server_p->servers--;
454 CurrUsers(server_p->class)--;
455
456 if(ServerConfIllegal(server_p) && !server_p->servers)
457 {
458 /* the class this one is using may need destroying too */
459 if(MaxUsers(server_p->class) < 0 && CurrUsers(server_p->class) <= 0)
460 free_class(server_p->class);
461
330fc5c1 462 rb_dlinkDelete(&server_p->node, &server_conf_list);
212380e3
AC
463 free_server_conf(server_p);
464 }
465}
466
467void
a3143c9b 468set_server_conf_autoconn(struct Client *source_p, const char *name, int newval)
212380e3
AC
469{
470 struct server_conf *server_p;
471
472 if((server_p = find_server_conf(name)) != NULL)
473 {
474 if(newval)
475 server_p->flags |= SERVER_AUTOCONN;
476 else
477 server_p->flags &= ~SERVER_AUTOCONN;
478
479 sendto_realops_snomask(SNO_GENERAL, L_ALL,
480 "%s has changed AUTOCONN for %s to %i",
481 get_oper_name(source_p), name, newval);
482 }
483 else
5366977b 484 sendto_one_notice(source_p, ":Can't find %s", name);
212380e3
AC
485}
486
53307da8
JT
487void
488disable_server_conf_autoconn(const char *name)
489{
490 struct server_conf *server_p;
491
492 server_p = find_server_conf(name);
493 if(server_p != NULL && server_p->flags & SERVER_AUTOCONN)
494 {
495 server_p->flags &= ~SERVER_AUTOCONN;
496
497 sendto_realops_snomask(SNO_GENERAL, L_ALL,
498 "Disabling AUTOCONN for %s because of error",
499 name);
500 ilog(L_SERVER, "Disabling AUTOCONN for %s because of error",
501 name);
502 }
503}
504
212380e3
AC
505struct ConfItem *
506find_xline(const char *gecos, int counter)
507{
508 struct ConfItem *aconf;
330fc5c1 509 rb_dlink_node *ptr;
212380e3 510
5cefa1d6 511 RB_DLINK_FOREACH(ptr, xline_conf_list.head)
212380e3
AC
512 {
513 aconf = ptr->data;
514
70ea02eb 515 if(match_esc(aconf->host, gecos))
212380e3
AC
516 {
517 if(counter)
518 aconf->port++;
519 return aconf;
520 }
521 }
522
523 return NULL;
524}
525
0fdb2570
JT
526struct ConfItem *
527find_xline_mask(const char *gecos)
528{
529 struct ConfItem *aconf;
330fc5c1 530 rb_dlink_node *ptr;
0fdb2570 531
5cefa1d6 532 RB_DLINK_FOREACH(ptr, xline_conf_list.head)
0fdb2570
JT
533 {
534 aconf = ptr->data;
535
70ea02eb 536 if(!irccmp(aconf->host, gecos))
0fdb2570
JT
537 return aconf;
538 }
539
540 return NULL;
541}
542
212380e3
AC
543struct ConfItem *
544find_nick_resv(const char *name)
545{
546 struct ConfItem *aconf;
330fc5c1 547 rb_dlink_node *ptr;
212380e3 548
5cefa1d6 549 RB_DLINK_FOREACH(ptr, resv_conf_list.head)
212380e3
AC
550 {
551 aconf = ptr->data;
552
70ea02eb 553 if(match_esc(aconf->host, name))
212380e3
AC
554 {
555 aconf->port++;
556 return aconf;
557 }
558 }
559
560 return NULL;
561}
562
0fdb2570
JT
563struct ConfItem *
564find_nick_resv_mask(const char *name)
565{
566 struct ConfItem *aconf;
330fc5c1 567 rb_dlink_node *ptr;
0fdb2570 568
5cefa1d6 569 RB_DLINK_FOREACH(ptr, resv_conf_list.head)
0fdb2570
JT
570 {
571 aconf = ptr->data;
572
70ea02eb 573 if(!irccmp(aconf->host, name))
0fdb2570
JT
574 return aconf;
575 }
576
577 return NULL;
578}
579
212380e3
AC
580/* clean_resv_nick()
581 *
582 * inputs - nick
583 * outputs - 1 if nick is vaild resv, 0 otherwise
584 * side effects -
585 */
586int
587clean_resv_nick(const char *nick)
588{
589 char tmpch;
590 int as = 0;
591 int q = 0;
592 int ch = 0;
593
594 if(*nick == '-' || IsDigit(*nick))
595 return 0;
596
597 while ((tmpch = *nick++))
598 {
599 if(tmpch == '?' || tmpch == '@' || tmpch == '#')
600 q++;
601 else if(tmpch == '*')
602 as++;
603 else if(IsNickChar(tmpch))
604 ch++;
605 else
606 return 0;
607 }
608
609 if(!ch && as)
610 return 0;
611
612 return 1;
613}
614
615/* valid_wild_card_simple()
616 *
617 * inputs - "thing" to test
618 * outputs - 1 if enough wildcards, else 0
619 * side effects -
620 */
621int
622valid_wild_card_simple(const char *data)
623{
624 const char *p;
625 char tmpch;
626 int nonwild = 0;
7d08aa89 627 int wild = 0;
212380e3
AC
628
629 /* check the string for minimum number of nonwildcard chars */
630 p = data;
631
632 while((tmpch = *p++))
633 {
634 /* found an escape, p points to the char after it, so skip
635 * that and move on.
636 */
7d08aa89 637 if(tmpch == '\\' && *p)
212380e3
AC
638 {
639 p++;
7d08aa89
JT
640 if(++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
641 return 1;
212380e3
AC
642 }
643 else if(!IsMWildChar(tmpch))
644 {
645 /* if we have enough nonwildchars, return */
646 if(++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
647 return 1;
648 }
7d08aa89
JT
649 else
650 wild++;
212380e3
AC
651 }
652
7d08aa89
JT
653 /* strings without wilds are also ok */
654 return wild == 0;
212380e3
AC
655}
656
657time_t
658valid_temp_time(const char *p)
659{
660 time_t result = 0;
661
662 while(*p)
663 {
664 if(IsDigit(*p))
665 {
666 result *= 10;
667 result += ((*p) & 0xF);
668 p++;
669 }
670 else
671 return -1;
672 }
673
674 if(result > (60 * 24 * 7 * 52))
675 result = (60 * 24 * 7 * 52);
676
677 return(result * 60);
678}
679
9197bc35 680/* Propagated bans are expired elsewhere. */
212380e3
AC
681static void
682expire_temp_rxlines(void *unused)
683{
684 struct ConfItem *aconf;
330fc5c1 685 rb_dlink_node *ptr;
637c4932 686 rb_dlink_node *next_ptr;
2fc6772e 687 rb_radixtree_iteration_state state;
212380e3 688
a4bf26dd 689 RB_RADIXTREE_FOREACH(aconf, &state, resv_tree)
212380e3 690 {
9197bc35
JT
691 if(aconf->lifetime != 0)
692 continue;
e3354945 693 if(aconf->hold && aconf->hold <= rb_current_time())
212380e3
AC
694 {
695 if(ConfigFileEntry.tkline_expire_notices)
696 sendto_realops_snomask(SNO_GENERAL, L_ALL,
697 "Temporary RESV for [%s] expired",
70ea02eb 698 aconf->host);
212380e3 699
a4bf26dd 700 rb_radixtree_delete(resv_tree, aconf->host);
212380e3 701 free_conf(aconf);
212380e3
AC
702 }
703 }
212380e3 704
637c4932 705 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, resv_conf_list.head)
212380e3
AC
706 {
707 aconf = ptr->data;
708
9197bc35
JT
709 if(aconf->lifetime != 0)
710 continue;
e3354945 711 if(aconf->hold && aconf->hold <= rb_current_time())
212380e3
AC
712 {
713 if(ConfigFileEntry.tkline_expire_notices)
714 sendto_realops_snomask(SNO_GENERAL, L_ALL,
715 "Temporary RESV for [%s] expired",
70ea02eb 716 aconf->host);
212380e3 717 free_conf(aconf);
330fc5c1 718 rb_dlinkDestroy(ptr, &resv_conf_list);
212380e3
AC
719 }
720 }
721
637c4932 722 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, xline_conf_list.head)
212380e3
AC
723 {
724 aconf = ptr->data;
725
9197bc35
JT
726 if(aconf->lifetime != 0)
727 continue;
e3354945 728 if(aconf->hold && aconf->hold <= rb_current_time())
212380e3
AC
729 {
730 if(ConfigFileEntry.tkline_expire_notices)
731 sendto_realops_snomask(SNO_GENERAL, L_ALL,
732 "Temporary X-line for [%s] expired",
70ea02eb 733 aconf->host);
212380e3 734 free_conf(aconf);
330fc5c1 735 rb_dlinkDestroy(ptr, &xline_conf_list);
212380e3
AC
736 }
737 }
738}
739
740unsigned long
741get_nd_count(void)
742{
330fc5c1 743 return(rb_dlink_list_length(&nd_list));
212380e3
AC
744}
745
212380e3
AC
746void
747add_nd_entry(const char *name)
748{
749 struct nd_entry *nd;
750
a4bf26dd 751 if(rb_dictionary_find(nd_dict, name) != NULL)
212380e3
AC
752 return;
753
398b6a73 754 nd = rb_bh_alloc(nd_heap);
55abcbb2 755
f427c8b0 756 rb_strlcpy(nd->name, name, sizeof(nd->name));
e3354945 757 nd->expire = rb_current_time() + ConfigFileEntry.nick_delay;
212380e3
AC
758
759 /* this list is ordered */
330fc5c1 760 rb_dlinkAddTail(nd, &nd->lnode, &nd_list);
b37021a4 761
a4bf26dd 762 rb_dictionary_add(nd_dict, nd->name, nd);
212380e3
AC
763}
764
765void
766free_nd_entry(struct nd_entry *nd)
767{
a4bf26dd 768 rb_dictionary_delete(nd_dict, nd->name);
b37021a4 769
330fc5c1 770 rb_dlinkDelete(&nd->lnode, &nd_list);
398b6a73 771 rb_bh_free(nd_heap, nd);
212380e3
AC
772}
773
774void
775expire_nd_entries(void *unused)
776{
777 struct nd_entry *nd;
330fc5c1 778 rb_dlink_node *ptr;
637c4932 779 rb_dlink_node *next_ptr;
212380e3 780
637c4932 781 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, nd_list.head)
212380e3
AC
782 {
783 nd = ptr->data;
784
785 /* this list is ordered - we can stop when we hit the first
786 * entry that doesnt expire..
787 */
e3354945 788 if(nd->expire > rb_current_time())
212380e3
AC
789 return;
790
791 free_nd_entry(nd);
792 }
793}
794
795void
796add_tgchange(const char *host)
797{
798 tgchange *target;
e410dcf5 799 rb_patricia_node_t *pnode;
212380e3
AC
800
801 if(find_tgchange(host))
802 return;
803
eddc2ab6 804 target = rb_malloc(sizeof(tgchange));
212380e3
AC
805 pnode = make_and_lookup(tgchange_tree, host);
806
807 pnode->data = target;
808 target->pnode = pnode;
809
47a03750 810 target->ip = rb_strdup(host);
e3354945 811 target->expiry = rb_current_time() + (60*60*12);
212380e3 812
330fc5c1 813 rb_dlinkAdd(target, &target->node, &tgchange_list);
212380e3
AC
814}
815
816tgchange *
817find_tgchange(const char *host)
818{
e410dcf5 819 rb_patricia_node_t *pnode;
212380e3 820
e410dcf5 821 if((pnode = rb_match_exact_string(tgchange_tree, host)))
212380e3
AC
822 return pnode->data;
823
824 return NULL;
825}