]> jfr.im git - irc/quakenet/newserv.git/blame - nick/nick.c
patricia trie changes
[irc/quakenet/newserv.git] / nick / nick.c
CommitLineData
c86edd1d
Q
1/* nick.c */
2
3#include "nick.h"
4#include "../lib/flags.h"
5#include "../lib/irc_string.h"
6#include "../lib/base64.h"
7#include "../irc/irc.h"
8#include "../irc/irc_config.h"
9#include "../core/error.h"
10#include "../core/hooks.h"
11#include "../lib/sstring.h"
12#include "../server/server.h"
13#include "../parser/parser.h"
87698d77 14#include "../lib/version.h"
103521a1 15#include "../core/nsmalloc.h"
16
c86edd1d
Q
17#include <stdlib.h>
18#include <string.h>
19#include <stdio.h>
20
70b0a4e5 21MODULE_VERSION("");
87698d77 22
c86edd1d
Q
23const flag umodeflags[] = {
24 { 'i', UMODE_INV },
25 { 'w', UMODE_WALLOPS },
26 { 'g', UMODE_DEBUG },
27 { 'o', UMODE_OPER },
28 { 'k', UMODE_SERVICE },
29 { 'X', UMODE_XOPER },
30 { 'd', UMODE_DEAF },
31 { 'r', UMODE_ACCOUNT },
32 { 'n', UMODE_HIDECHAN },
33 { 'x', UMODE_HIDEHOST },
34 { 'h', UMODE_SETHOST },
35 { 'R', UMODE_REGPRIV },
36 { 'I', UMODE_HIDEIDLE },
e98d808a 37 { 'P', UMODE_PARANOID },
c86edd1d
Q
38 { '\0', 0 } };
39
c153c0dc
CP
40const flag accountflags[] = {
41 { 's', AFLAG_STAFF },
42 { 'd', AFLAG_DEVELOPER },
43 { '\0', 0 } };
44
c86edd1d
Q
45#define nickhash(x) ((crc32i(x))%NICKHASHSIZE)
46
47nick *nicktable[NICKHASHSIZE];
48nick **servernicks[MAXSERVERS];
49
50sstring *nickextnames[MAXNICKEXTS];
51
52void nickstats(int hooknum, void *arg);
53
54void _init() {
e31727be 55 unsigned int i;
56 authname *anp;
57
58 /* Clear up the nicks in authext */
59 for (i=0;i<AUTHNAMEHASHSIZE;i++)
60 for (anp=authnametable[i];anp;anp=anp->next)
61 anp->nicks=NULL;
62
c86edd1d
Q
63 initnickalloc();
64 initnickhelpers();
65 memset(nicktable,0,sizeof(nicktable));
66 memset(servernicks,0,sizeof(servernicks));
67
68 /* Register our hooks */
69 registerhook(HOOK_SERVER_NEWSERVER,&handleserverchange);
70 registerhook(HOOK_SERVER_LOSTSERVER,&handleserverchange);
71 registerhook(HOOK_CORE_STATSREQUEST,&nickstats);
72
73 /* And our server handlers */
74 registerserverhandler("N",&handlenickmsg,10);
75 registerserverhandler("D",&handlekillmsg,2);
76 registerserverhandler("Q",&handlequitmsg,1);
77 registerserverhandler("M",&handleusermodemsg,3);
78 registerserverhandler("W",&handlewhoismsg,2);
47657339 79 registerserverhandler("AC",&handleaccountmsg,4);
c86edd1d
Q
80 registerserverhandler("R",&handlestatsmsg,2);
81
82 /* Fake the addition of our own server */
83 handleserverchange(HOOK_SERVER_NEWSERVER,(void *)numerictolong(mynumeric->content,2));
84}
85
103521a1 86void _fini() {
9cf0b03f
CP
87 nick *np;
88 int i;
89
707c5824 90 fininickhelpers();
9cf0b03f
CP
91
92 for (i=0;i<NICKHASHSIZE;i++) {
93 for (np=nicktable[i];np;np=np->next) {
94 freesstring(np->shident);
95 freesstring(np->sethost);
96 }
97 }
98
df5ab174 99 nsfreeall(POOL_NICK);
707c5824 100
103521a1 101 /* Free the hooks */
102 deregisterhook(HOOK_SERVER_NEWSERVER,&handleserverchange);
103 deregisterhook(HOOK_SERVER_LOSTSERVER,&handleserverchange);
104 deregisterhook(HOOK_CORE_STATSREQUEST,&nickstats);
105
106 /* And our server handlers */
107 deregisterserverhandler("N",&handlenickmsg);
108 deregisterserverhandler("D",&handlekillmsg);
109 deregisterserverhandler("Q",&handlequitmsg);
110 deregisterserverhandler("M",&handleusermodemsg);
111 deregisterserverhandler("W",&handlewhoismsg);
112 deregisterserverhandler("AC",&handleaccountmsg);
113 deregisterserverhandler("R",&handlestatsmsg);
114}
115
c86edd1d
Q
116/*
117 * This function handles servers appearing and disappearing.
118 * For a new server, the client table is allocated.
119 * For a disappearing server, all it's clients are killed and the client table is freed.
120 */
121
122void handleserverchange(int hooknum, void *arg) {
c3db6f7e 123 long servernum;
c86edd1d
Q
124 int i;
125
c3db6f7e 126 servernum=(long)arg;
c86edd1d
Q
127
128 switch(hooknum) {
129 case HOOK_SERVER_NEWSERVER:
103521a1 130 servernicks[servernum]=(nick **)nsmalloc(POOL_NICK,(serverlist[servernum].maxusernum+1)*sizeof(nick **));
c86edd1d
Q
131 memset(servernicks[servernum],0,(serverlist[servernum].maxusernum+1)*sizeof(nick **));
132 break;
133
134 case HOOK_SERVER_LOSTSERVER:
135 for (i=0;i<=serverlist[servernum].maxusernum;i++) {
136 if (servernicks[servernum][i]!=NULL) {
137 deletenick(servernicks[servernum][i]);
138 }
139 }
2a010087 140 nsfree(POOL_NICK,servernicks[servernum]);
c86edd1d
Q
141 break;
142 }
143}
144
145/*
146 * deletenick:
147 *
148 * This function handles the removal of a nick from the network
149 */
150
151void deletenick(nick *np) {
152 nick **nh;
153
154 /* Fire the hook. This will deal with removal from channels etc. */
155 triggerhook(HOOK_NICK_LOSTNICK, np);
156
157 /* Release the realname and hostname parts */
158
159 for (nh=&(np->realname->nicks);*nh;nh=&((*nh)->nextbyrealname)) {
160 if (*nh==np) {
161 *nh=np->nextbyrealname;
162 break;
163 }
164 }
165
166 for (nh=&(np->host->nicks);*nh;nh=&((*nh)->nextbyhost)) {
167 if (*nh==np) {
168 *nh=np->nextbyhost;
169 break;
170 }
171 }
172
173 releaserealname(np->realname);
174 releasehost(np->host);
175
47657339
C
176 if(IsAccount(np) && np->auth)
177 {
178 np->auth->usercount--;
179
180 for (nh=&(np->auth->nicks);*nh;nh=&((*nh)->nextbyauthname)) {
181 if (*nh==np) {
182 *nh=np->nextbyauthname;
183 break;
184 }
185 }
186
187 releaseauthname(np->auth);
188 }
189
c86edd1d
Q
190 freesstring(np->shident); /* freesstring(NULL) is OK */
191 freesstring(np->sethost);
192
96644df6 193 node_decrement_usercount(np->ipnode);
526e7c1d
P
194 derefnode(iptree, np->ipnode);
195
196 /* TODO: figure out how to cleanly remove nodes without affecting other modules */
197
c86edd1d
Q
198 /* Delete the nick from the servernick table */
199 *(gethandlebynumericunsafe(np->numeric))=NULL;
200
201 /* Remove the nick from the hash table */
202 removenickfromhash(np);
203
204 freenick(np);
205}
206
207void addnicktohash(nick *np) {
208 np->next=nicktable[nickhash(np->nick)];
209 nicktable[nickhash(np->nick)]=np;
210}
211
212void removenickfromhash(nick *np) {
213 nick **nh;
214
215 for (nh=&(nicktable[nickhash(np->nick)]);*nh;nh=&((*nh)->next)) {
216 if ((*nh)==np) {
217 (*nh)=np->next;
218 break;
219 }
220 }
221}
222
223nick *getnickbynick(const char *name) {
224 nick *np;
225
226 for (np=nicktable[nickhash(name)];np;np=np->next) {
227 if (!ircd_strcmp(np->nick,name))
228 return np;
229 }
230
231 return NULL;
232}
233
234void nickstats(int hooknum, void *arg) {
235 int total,maxchain,curchain,i,buckets;
236 nick *np;
237 char buf[200];
238
239 /* Get nick stats */
240 buckets=total=maxchain=curchain=0;
241 for (i=0;i<NICKHASHSIZE;i++,curchain=0) {
242 np=nicktable[i];
243 if (np!=NULL) {
244 buckets++;
245 for (;np;np=np->next) {
246 total++;
247 curchain++;
248 }
249 }
250 if (curchain>maxchain) {
251 maxchain=curchain;
252 }
253 }
254
c3db6f7e 255 if ((long)arg>5) {
c86edd1d
Q
256 /* Full stats */
257 sprintf(buf,"Nick : %6d nicks (HASH: %6d/%6d, chain %3d)",total,buckets,NICKHASHSIZE,maxchain);
c3db6f7e 258 } else if ((long)arg>2) {
c86edd1d
Q
259 sprintf(buf,"Nick : %6d users on network.",total);
260 }
261
c3db6f7e 262 if ((long)arg>2) {
c86edd1d
Q
263 triggerhook(HOOK_CORE_STATSREPLY,buf);
264 }
265}
266
267int registernickext(const char *name) {
268 int i;
269
270 if (findnickext(name)!=-1) {
271 Error("nick",ERR_WARNING,"Tried to register duplicate nick extension %s",name);
272 return -1;
273 }
274
275 for (i=0;i<MAXNICKEXTS;i++) {
276 if (nickextnames[i]==NULL) {
277 nickextnames[i]=getsstring(name,100);
278 return i;
279 }
280 }
281
47657339 282 Error("nick",ERR_WARNING,"Tried to register too many nick extensions: %s",name);
c86edd1d
Q
283 return -1;
284}
285
286int findnickext(const char *name) {
287 int i;
288
289 for (i=0;i<MAXNICKEXTS;i++) {
290 if (nickextnames[i]!=NULL && !ircd_strcmp(name,nickextnames[i]->content)) {
291 return i;
292 }
293 }
294
295 return -1;
296}
297
298void releasenickext(int index) {
299 int i;
300 nick *np;
301
302 freesstring(nickextnames[index]);
303 nickextnames[index]=NULL;
304
305 for (i=0;i<NICKHASHSIZE;i++) {
306 for (np=nicktable[i];np;np=np->next) {
307 np->exts[index]=NULL;
308 }
309 }
310}
311
312/* visiblehostmask
313 * Produces the "apparent" hostmask as seen by network users.
314 */
315
316char *visiblehostmask(nick *np, char *buf) {
28252fef 317 char uhbuf[USERLEN+HOSTLEN+2];
318
319 visibleuserhost(np, uhbuf);
320 sprintf(buf,"%s!%s",np->nick,uhbuf);
321
322 return buf;
323}
324
325/* visibleuserhost
326 * As above without nick
327 */
328
329char *visibleuserhost(nick *np, char *buf) {
c86edd1d
Q
330 char hostbuf[HOSTLEN+1];
331 char *ident, *host;
332
333 ident=np->ident;
334 host=np->host->name->content;
335
336 if (IsSetHost(np)) {
337 if (np->shident) {
338 ident=np->shident->content;
339 }
340 if (np->sethost) {
341 host=np->sethost->content;
342 }
343 } else if (IsAccount(np) && IsHideHost(np)) {
344 sprintf(hostbuf,"%s.%s", np->authname, HIS_HIDDENHOST);
345 host=hostbuf;
346 }
347
28252fef 348 sprintf(buf,"%s@%s",ident,host);
c86edd1d
Q
349
350 return buf;
351}
352
353#if 0
354
355/*
356 * gethandlebynumeric:
357 * Given a numeric, gives the location in the servernicks table
358 * where it should be. Does not check that the nick currently found
359 * there (if any) has the correct numeric; this is left to the
360 * calling function to figure out.
361 */
362
363nick **gethandlebynumeric(long numeric) {
364 int servernum;
365 int maskednum;
366 server *serv;
367
368 /* Shift off the client identifier part of the numeric to get the server ID */
369 servernum=(numeric>>18);
370
371 if ((serv=getserverdata(servernum))==NULL) {
372 Error("nick",ERR_WARNING,"Numeric %ld refers to non-existent server %d",numeric,servernum);
373 return NULL;
374 }
375
376 /* Compute the masked numeric */
377 maskednum=numeric&(serv->maxusernum);
378
379 return (servernicks[servernum])+maskednum;
380}
381
382/*
383 * getnickbynumeric[str]()
384 * These functions retrieve a nick based on it's numeric on the network
385 * Use the approriate function depending on how your numeric is expressed..
386 */
387
388nick *getnickbynumeric(long numeric) {
389 nick **nh;
390
391 nh=gethandlebynumeric(numeric);
392
393 if ((*nh) && ((*nh)->numeric!=numeric)) {
394 /* We found a masked numeric match, but the actual numeric
395 * is different. This counts as a miss. */
396 return NULL;
397 }
398
399 return (*nh);
400}
401
402nick *getnickbynumericstr(char *numericstr) {
403 return getnickbynumeric(numerictolong(numericstr,5));
404}
405
406#endif
526e7c1d 407