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