]> jfr.im git - solanum.git/blame - ircd/whowas.c
ircd/authproc.c: avoid crash on lack of any configured DNSBLs
[solanum.git] / ircd / whowas.c
CommitLineData
212380e3
AC
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * whowas.c: WHOWAS user cache.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
b47f8a4f 7 * Copyright (C) 2002-2012 ircd-ratbox development team
3fc0499e 8 * Copyright (C) 2016 Ariadne Conill <ariadne@dereferenced.org>
212380e3
AC
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
b47f8a4f 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
212380e3 23 * USA
212380e3
AC
24 */
25
26#include "stdinc.h"
212380e3 27#include "hash.h"
b47f8a4f 28#include "whowas.h"
4562c604 29#include "match.h"
212380e3 30#include "ircd.h"
212380e3 31#include "numeric.h"
b47f8a4f 32#include "s_assert.h"
212380e3
AC
33#include "s_serv.h"
34#include "s_user.h"
35#include "send.h"
36#include "s_conf.h"
b47f8a4f
AC
37#include "client.h"
38#include "send.h"
39#include "logger.h"
c88cdb00 40#include "scache.h"
a4bf26dd 41#include "rb_radixtree.h"
212380e3 42
b47f8a4f
AC
43struct whowas_top
44{
45 char *name;
46 rb_dlink_list wwlist;
47};
212380e3 48
2fc6772e 49static rb_radixtree *whowas_tree = NULL;
b47f8a4f
AC
50static rb_dlink_list whowas_list = {NULL, NULL, 0};
51static unsigned int whowas_list_length = NICKNAMEHISTORYLENGTH;
52static void whowas_trim(void *unused);
212380e3 53
b47f8a4f
AC
54static void
55whowas_free_wtop(struct whowas_top *wtop)
56{
57 if(rb_dlink_list_length(&wtop->wwlist) == 0)
58 {
a4bf26dd 59 rb_radixtree_delete(whowas_tree, wtop->name);
b47f8a4f
AC
60 rb_free(wtop->name);
61 rb_free(wtop);
62 }
63}
212380e3 64
b47f8a4f
AC
65static struct whowas_top *
66whowas_get_top(const char *name)
212380e3 67{
b47f8a4f
AC
68 struct whowas_top *wtop;
69
a4bf26dd 70 wtop = rb_radixtree_retrieve(whowas_tree, name);
b47f8a4f
AC
71 if (wtop != NULL)
72 return wtop;
73
74 wtop = rb_malloc(sizeof(struct whowas_top));
75 wtop->name = rb_strdup(name);
a4bf26dd 76 rb_radixtree_add(whowas_tree, wtop->name, wtop);
b47f8a4f
AC
77
78 return wtop;
212380e3
AC
79}
80
b47f8a4f
AC
81rb_dlink_list *
82whowas_get_list(const char *name)
212380e3 83{
b47f8a4f 84 struct whowas_top *wtop;
a4bf26dd 85 wtop = rb_radixtree_retrieve(whowas_tree, name);
b47f8a4f
AC
86 if(wtop == NULL)
87 return NULL;
88 return &wtop->wwlist;
89}
212380e3 90
b47f8a4f
AC
91void
92whowas_add_history(struct Client *client_p, int online)
93{
94 struct whowas_top *wtop;
95 struct Whowas *who;
212380e3
AC
96 s_assert(NULL != client_p);
97
98 if(client_p == NULL)
99 return;
100
b47f8a4f
AC
101 /* trim some of the entries if we're getting well over our history length */
102 if(rb_dlink_list_length(&whowas_list) > whowas_list_length + 100)
103 whowas_trim(NULL);
104
105 wtop = whowas_get_top(client_p->name);
106 who = rb_malloc(sizeof(struct Whowas));
107 who->wtop = wtop;
e3354945 108 who->logoff = rb_current_time();
b47f8a4f 109
f427c8b0 110 rb_strlcpy(who->name, client_p->name, sizeof(who->name));
b47f8a4f
AC
111 rb_strlcpy(who->username, client_p->username, sizeof(who->username));
112 rb_strlcpy(who->hostname, client_p->host, sizeof(who->hostname));
113 rb_strlcpy(who->realname, client_p->info, sizeof(who->realname));
114 rb_strlcpy(who->sockhost, client_p->sockhost, sizeof(who->sockhost));
9dd98618 115 rb_strlcpy(who->suser, client_p->user->suser, sizeof(who->suser));
b47f8a4f 116
364e59f8
JT
117 who->flags = (IsIPSpoof(client_p) ? WHOWAS_IP_SPOOFING : 0) |
118 (IsDynSpoof(client_p) ? WHOWAS_DYNSPOOF : 0);
212380e3 119
b47f8a4f 120 /* this is safe do to with the servername cache */
994544c2 121 who->servername = scache_get_name(client_p->servptr->serv->nameinfo);
212380e3
AC
122
123 if(online)
124 {
125 who->online = client_p;
b47f8a4f 126 rb_dlinkAdd(who, &who->cnode, &client_p->whowas_clist);
212380e3
AC
127 }
128 else
129 who->online = NULL;
b47f8a4f
AC
130
131 rb_dlinkAdd(who, &who->wnode, &wtop->wwlist);
132 rb_dlinkAdd(who, &who->whowas_node, &whowas_list);
212380e3
AC
133}
134
b47f8a4f
AC
135
136void
137whowas_off_history(struct Client *client_p)
212380e3 138{
b47f8a4f 139 rb_dlink_node *ptr, *next;
212380e3 140
b47f8a4f 141 RB_DLINK_FOREACH_SAFE(ptr, next, client_p->whowas_clist.head)
212380e3 142 {
b47f8a4f
AC
143 struct Whowas *who = ptr->data;
144 who->online = NULL;
145 rb_dlinkDelete(&who->cnode, &client_p->whowas_clist);
212380e3
AC
146 }
147}
148
b47f8a4f
AC
149struct Client *
150whowas_get_history(const char *nick, time_t timelimit)
212380e3 151{
b47f8a4f
AC
152 struct whowas_top *wtop;
153 rb_dlink_node *ptr;
154
a4bf26dd 155 wtop = rb_radixtree_retrieve(whowas_tree, nick);
b47f8a4f
AC
156 if(wtop == NULL)
157 return NULL;
212380e3 158
e3354945 159 timelimit = rb_current_time() - timelimit;
b47f8a4f
AC
160
161 RB_DLINK_FOREACH_PREV(ptr, wtop->wwlist.tail)
212380e3 162 {
b47f8a4f
AC
163 struct Whowas *who = ptr->data;
164 if(who->logoff >= timelimit)
165 {
166 return who->online;
167 }
212380e3 168 }
b47f8a4f 169
212380e3
AC
170 return NULL;
171}
172
b47f8a4f
AC
173static void
174whowas_trim(void *unused)
212380e3 175{
b47f8a4f 176 long over;
212380e3 177
b47f8a4f
AC
178 if(rb_dlink_list_length(&whowas_list) < whowas_list_length)
179 return;
180 over = rb_dlink_list_length(&whowas_list) - whowas_list_length;
212380e3 181
b47f8a4f
AC
182 /* remove whowas entries over the configured length */
183 for(long i = 0; i < over; i++)
212380e3 184 {
b47f8a4f
AC
185 if(whowas_list.tail != NULL && whowas_list.tail->data != NULL)
186 {
187 struct Whowas *twho = whowas_list.tail->data;
188 if(twho->online != NULL)
189 rb_dlinkDelete(&twho->cnode, &twho->online->whowas_clist);
190 rb_dlinkDelete(&twho->wnode, &twho->wtop->wwlist);
191 rb_dlinkDelete(&twho->whowas_node, &whowas_list);
192 whowas_free_wtop(twho->wtop);
193 rb_free(twho);
194 }
212380e3 195 }
212380e3
AC
196}
197
b47f8a4f
AC
198void
199whowas_init(void)
212380e3 200{
a4bf26dd 201 whowas_tree = rb_radixtree_create("whowas", irccasecanon);
b47f8a4f
AC
202 if(whowas_list_length == 0)
203 {
204 whowas_list_length = NICKNAMEHISTORYLENGTH;
205 }
206 rb_event_add("whowas_trim", whowas_trim, NULL, 10);
212380e3
AC
207}
208
b47f8a4f
AC
209void
210whowas_set_size(int len)
212380e3 211{
b47f8a4f
AC
212 whowas_list_length = len;
213 whowas_trim(NULL);
212380e3
AC
214}
215
b47f8a4f
AC
216void
217whowas_memory_usage(size_t * count, size_t * memused)
212380e3 218{
b47f8a4f
AC
219 *count = rb_dlink_list_length(&whowas_list);
220 *memused += *count * sizeof(struct Whowas);
a4bf26dd 221 *memused += sizeof(struct whowas_top) * rb_radixtree_size(whowas_tree);
212380e3 222}