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