]> jfr.im git - irc/quakenet/newserv.git/blame - whowas/whowas.c
GLINES: fix null pointer deref in trustgline / trustungline
[irc/quakenet/newserv.git] / whowas / whowas.c
CommitLineData
fa6819a7 1#include <string.h>
0eb4cbd3 2#include <stdio.h>
fa6819a7
GB
3#include "../core/hooks.h"
4#include "../control/control.h"
5#include "../irc/irc.h"
6#include "../lib/irc_string.h"
363e3ed0 7#include "../lib/version.h"
291fdf5f 8#include "../core/config.h"
fa6819a7
GB
9#include "whowas.h"
10
5731b78b
CP
11#define XStringify(x) Stringify(x)
12#define Stringify(x) #x
13
363e3ed0 14MODULE_VERSION("");
fa6819a7 15
291fdf5f 16whowas *whowasrecs;
0495c1d1 17int whowasoffset = 0;
291fdf5f 18int whowasmax;
d6385de2 19
0495c1d1 20whowas *whowas_fromnick(nick *np, int standalone) {
fa6819a7 21 whowas *ww;
0eb4cbd3
GB
22 nick *wnp;
23 struct irc_in_addr ipaddress_canonical;
dd33b9ca 24 void *args[2];
fa6819a7
GB
25
26 /* Create a new record. */
0495c1d1
GB
27 if (standalone)
28 ww = malloc(sizeof(whowas));
29 else {
30 ww = &whowasrecs[whowasoffset];
31 whowas_clean(ww);
291fdf5f 32 whowasoffset = (whowasoffset + 1) % whowasmax;
0495c1d1
GB
33 }
34
4030a47e 35 memset(ww, 0, sizeof(whowas));
0eb4cbd3 36
0495c1d1 37 wnp = &ww->nick;
0eb4cbd3
GB
38 memset(wnp, 0, sizeof(nick));
39 strncpy(wnp->nick, np->nick, NICKLEN + 1);
40 wnp->numeric = np->numeric;
41 strncpy(wnp->ident, np->ident, USERLEN + 1);
42
43 wnp->host = newhost();
44 memset(wnp->host, 0, sizeof(host));
45 wnp->host->name = getsstring(np->host->name->content, HOSTLEN);
46
47 wnp->realname = newrealname();
48 memset(wnp->realname, 0, sizeof(realname));
49 wnp->realname->name = getsstring(np->realname->name->content, REALLEN);
81e02f8e
GB
50 wnp->shident = np->shident ? getsstring(np->shident->content, 512) : NULL;
51 wnp->sethost = np->sethost ? getsstring(np->sethost->content, 512) : NULL;
52 wnp->opername = np->opername ? getsstring(np->opername->content, 512) : NULL;
0eb4cbd3
GB
53 wnp->umodes = np->umodes;
54 if (np->auth) {
55 wnp->auth = newauthname();
56 memset(wnp->auth, 0, sizeof(authname));
57 wnp->auth->userid = np->auth->userid;
58 strncpy(wnp->auth->name, np->auth->name, ACCOUNTLEN + 1);
b965fa47 59 wnp->authname = wnp->auth->name;
0eb4cbd3 60 }
0eb4cbd3
GB
61 wnp->timestamp = np->timestamp;
62 wnp->accountts = np->accountts;
63 wnp->away = np->away ? getsstring(np->away->content, 512) : NULL;
64
65 memcpy(&wnp->ipaddress, &np->ipaddress, sizeof(struct irc_in_addr));
66
67 ip_canonicalize_tunnel(&ipaddress_canonical, &np->ipaddress);
68 wnp->ipnode = refnode(iptree, &ipaddress_canonical, PATRICIA_MAXBITS);
69
70 wnp->next = (nick *)ww; /* Yuck. */
71
0eb4cbd3 72 ww->timestamp = getnettime();
a45da344 73 ww->type = WHOWAS_USED;
fa6819a7 74
dd33b9ca
GB
75 args[0] = ww;
76 args[1] = np;
77 triggerhook(HOOK_WHOWAS_NEWRECORD, args);
78
4030a47e
GB
79 return ww;
80}
d6385de2 81
0495c1d1 82void whowas_clean(whowas *ww) {
0eb4cbd3
GB
83 nick *np;
84
0495c1d1 85 if (!ww || ww->type == WHOWAS_UNUSED)
accce086
GB
86 return;
87
dd33b9ca
GB
88 triggerhook(HOOK_WHOWAS_LOSTRECORD, ww);
89
0495c1d1 90 np = &ww->nick;
0eb4cbd3
GB
91 freesstring(np->host->name);
92 freehost(np->host);
93 freesstring(np->realname->name);
94 freerealname(np->realname);
95 freesstring(np->shident);
96 freesstring(np->sethost);
97 freesstring(np->opername);
98 freeauthname(np->auth);
99 freesstring(np->away);
291fdf5f 100 derefnode(iptree, np->ipnode);
accce086 101 freesstring(ww->reason);
291fdf5f 102 freesstring(ww->newnick);
0495c1d1 103 ww->type = WHOWAS_UNUSED;
accce086
GB
104}
105
0495c1d1
GB
106void whowas_free(whowas *ww) {
107 whowas_clean(ww);
108 free(ww);
fa6819a7 109}
4030a47e
GB
110
111static void whowas_handlequitorkill(int hooknum, void *arg) {
112 void **args = arg;
113 nick *np = args[0];
114 char *reason = args[1];
115 char *rreason;
116 char resbuf[512];
117 whowas *ww;
118
4030a47e 119 /* Create a new record. */
0495c1d1 120 ww = whowas_fromnick(np, 0);
4030a47e
GB
121
122 if (hooknum == HOOK_NICK_KILL) {
123 if ((rreason = strchr(reason, ' '))) {
124 sprintf(resbuf, "Killed%s", rreason);
125 reason = resbuf;
126 }
127
128 ww->type = WHOWAS_KILL;
98005421
GB
129 } else {
130 if (strncmp(reason, "G-lined", 7) == 0)
131 ww->type = WHOWAS_KILL;
132 else
133 ww->type = WHOWAS_QUIT;
134 }
4030a47e
GB
135
136 ww->reason = getsstring(reason, WW_REASONLEN);
4030a47e
GB
137}
138
139static void whowas_handlerename(int hooknum, void *arg) {
140 void **args = arg;
141 nick *np = args[0];
142 char *oldnick = args[1];
143 whowas *ww;
0eb4cbd3 144 nick *wnp;
4030a47e 145
0495c1d1 146 ww = whowas_fromnick(np, 0);
4030a47e 147 ww->type = WHOWAS_RENAME;
0495c1d1 148 wnp = &ww->nick;
0eb4cbd3
GB
149 ww->newnick = getsstring(wnp->nick, NICKLEN);
150 strncpy(wnp->nick, oldnick, NICKLEN + 1);
4030a47e
GB
151}
152
0495c1d1 153whowas *whowas_chase(const char *target, int maxage) {
56cab147 154 whowas *ww;
0495c1d1 155 nick *wnp;
56cab147 156 time_t now;
0495c1d1 157 int i;
56cab147
GB
158
159 now = getnettime();
160
291fdf5f
CP
161 for (i = whowasoffset + whowasmax - 1; i >= whowasoffset; i--) {
162 ww = &whowasrecs[i % whowasmax];
0495c1d1
GB
163
164 if (ww->type == WHOWAS_UNUSED)
165 continue;
166
167 wnp = &ww->nick;
168
0eb4cbd3 169 if (ww->timestamp < now - maxage)
56cab147
GB
170 break; /* records are in timestamp order, we're done */
171
0495c1d1 172 if (ircd_strcmp(wnp->nick, target) == 0)
56cab147
GB
173 return ww;
174 }
175
176 return NULL;
177}
178
0eb4cbd3 179const char *whowas_format(whowas *ww) {
0495c1d1 180 nick *np = &ww->nick;
0eb4cbd3 181 static char buf[512];
accce086 182 char timebuf[30];
0eb4cbd3 183 char hostmask[512];
accce086 184
432206be 185 snprintf(hostmask, sizeof(hostmask), "%s!%s@%s%s%s [%s] (%s)",
0eb4cbd3
GB
186 np->nick, np->ident, np->host->name->content,
187 np->auth ? "/" : "", np->auth ? np->authname : "",
fdcb5d66 188 IPtostr(np->ipaddress),
432206be 189 printflags(np->umodes, umodeflags));
0eb4cbd3 190 strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime(&(ww->timestamp)));
accce086
GB
191
192 if (ww->type == WHOWAS_RENAME)
0eb4cbd3 193 snprintf(buf, sizeof(buf), "[%s] NICK %s r(%s) -> %s", timebuf, hostmask, np->realname->name->content, ww->newnick->content);
accce086 194 else
0eb4cbd3
GB
195 snprintf(buf, sizeof(buf), "[%s] %s %s r(%s): %s", timebuf, (ww->type == WHOWAS_QUIT) ? "QUIT" : "KILL", hostmask, np->realname->name->content, ww->reason->content);
196
197 return buf;
198}
199
dd33b9ca
GB
200const char *whowas_formatchannels(whowas *ww) {
201 static char buf[512];
202 int i, first = 1;
203
204 strcpy(buf, "Channels: ");
205
206 for (i = 0; i < WW_MAXCHANNELS; i++) {
207 if (!ww->channels[i])
208 break;
209
210 if (!first)
211 strncat(buf, ", ", sizeof(buf));
212 else
213 first = 0;
214
215 strncat(buf, ww->channels[i]->name->content, sizeof(buf));
216 }
217
218 if (!ww->channels[0])
219 strncat(buf, "(No channels.)", sizeof(buf));
220
221 buf[sizeof(buf) - 1] = '\0';
222
223 return buf;
224}
225
0eb4cbd3
GB
226unsigned int nextwhowasmarker() {
227 whowas *ww;
0495c1d1 228 int i;
0eb4cbd3
GB
229 static unsigned int whowasmarker=0;
230
231 whowasmarker++;
232
233 if (!whowasmarker) {
234 /* If we wrapped to zero, zap the marker on all records */
291fdf5f
CP
235 for (i = 0; i < whowasmax; i++) {
236 ww = &whowasrecs[i % whowasmax];
0495c1d1
GB
237 ww->marker=0;
238 }
239
0eb4cbd3
GB
240 whowasmarker++;
241 }
242
243 return whowasmarker;
accce086
GB
244}
245
4030a47e 246void _init(void) {
291fdf5f
CP
247 {
248 sstring *temp = getcopyconfigitem("whowas", "maxentries", XStringify(WW_DEFAULT_MAXENTRIES), 10);
249 whowasmax = atoi(temp->content);
250 freesstring(temp);
251 }
252 whowasrecs = calloc(whowasmax, sizeof(whowas));
8bf19136 253
4030a47e
GB
254 registerhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
255 registerhook(HOOK_NICK_KILL, whowas_handlequitorkill);
256 registerhook(HOOK_NICK_RENAME, whowas_handlerename);
257}
258
259void _fini(void) {
0495c1d1
GB
260 int i;
261 whowas *ww;
262
4030a47e
GB
263 deregisterhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
264 deregisterhook(HOOK_NICK_KILL, whowas_handlequitorkill);
265 deregisterhook(HOOK_NICK_RENAME, whowas_handlerename);
266
291fdf5f 267 for (i = 0; i < whowasmax; i++) {
96fa425f 268 ww = &whowasrecs[i];
0495c1d1
GB
269 whowas_clean(ww);
270 }
291fdf5f
CP
271
272 free(whowasrecs);
4030a47e 273}