]>
jfr.im git - irc/quakenet/newserv.git/blob - nick/nick.c
2b949d971f4e872adda4db9a73c13b66a440e1e5
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"
14 #include "../lib/version.h"
21 const flag umodeflags
[] = {
23 { 'w', UMODE_WALLOPS
},
26 { 'k', UMODE_SERVICE
},
29 { 'r', UMODE_ACCOUNT
},
30 { 'n', UMODE_HIDECHAN
},
31 { 'x', UMODE_HIDEHOST
},
32 { 'h', UMODE_SETHOST
},
33 { 'R', UMODE_REGPRIV
},
34 { 'I', UMODE_HIDEIDLE
},
37 #define nickhash(x) ((crc32i(x))%NICKHASHSIZE)
39 nick
*nicktable
[NICKHASHSIZE
];
40 nick
**servernicks
[MAXSERVERS
];
42 sstring
*nickextnames
[MAXNICKEXTS
];
43 sstring
*nodeextnames
[PATRICIA_MAXSLOTS
];
44 patricia_tree_t
*iptree
;
45 sstring
*authnameextnames
[MAXAUTHNAMEEXTS
];
47 void nickstats(int hooknum
, void *arg
);
52 memset(nicktable
,0,sizeof(nicktable
));
53 memset(servernicks
,0,sizeof(servernicks
));
55 /* Register our hooks */
56 registerhook(HOOK_SERVER_NEWSERVER
,&handleserverchange
);
57 registerhook(HOOK_SERVER_LOSTSERVER
,&handleserverchange
);
58 registerhook(HOOK_CORE_STATSREQUEST
,&nickstats
);
60 /* And our server handlers */
61 registerserverhandler("N",&handlenickmsg
,10);
62 registerserverhandler("D",&handlekillmsg
,2);
63 registerserverhandler("Q",&handlequitmsg
,1);
64 registerserverhandler("M",&handleusermodemsg
,3);
65 registerserverhandler("W",&handlewhoismsg
,2);
66 registerserverhandler("AC",&handleaccountmsg
,4);
67 registerserverhandler("R",&handlestatsmsg
,2);
69 /* Fake the addition of our own server */
70 handleserverchange(HOOK_SERVER_NEWSERVER
,(void *)numerictolong(mynumeric
->content
,2));
72 iptree
= patricia_new_tree(PATRICIA_MAXBITS
);
76 * This function handles servers appearing and disappearing.
77 * For a new server, the client table is allocated.
78 * For a disappearing server, all it's clients are killed and the client table is freed.
81 void handleserverchange(int hooknum
, void *arg
) {
88 case HOOK_SERVER_NEWSERVER
:
89 servernicks
[servernum
]=(nick
**)malloc((serverlist
[servernum
].maxusernum
+1)*sizeof(nick
**));
90 memset(servernicks
[servernum
],0,(serverlist
[servernum
].maxusernum
+1)*sizeof(nick
**));
93 case HOOK_SERVER_LOSTSERVER
:
94 for (i
=0;i
<=serverlist
[servernum
].maxusernum
;i
++) {
95 if (servernicks
[servernum
][i
]!=NULL
) {
96 deletenick(servernicks
[servernum
][i
]);
99 free(servernicks
[servernum
]);
107 * This function handles the removal of a nick from the network
110 void deletenick(nick
*np
) {
113 /* Fire the hook. This will deal with removal from channels etc. */
114 triggerhook(HOOK_NICK_LOSTNICK
, np
);
116 /* Release the realname and hostname parts */
118 for (nh
=&(np
->realname
->nicks
);*nh
;nh
=&((*nh
)->nextbyrealname
)) {
120 *nh
=np
->nextbyrealname
;
125 for (nh
=&(np
->host
->nicks
);*nh
;nh
=&((*nh
)->nextbyhost
)) {
132 releaserealname(np
->realname
);
133 releasehost(np
->host
);
135 if(IsAccount(np
) && np
->auth
)
137 np
->auth
->usercount
--;
139 for (nh
=&(np
->auth
->nicks
);*nh
;nh
=&((*nh
)->nextbyauthname
)) {
141 *nh
=np
->nextbyauthname
;
146 releaseauthname(np
->auth
);
149 freesstring(np
->shident
); /* freesstring(NULL) is OK */
150 freesstring(np
->sethost
);
152 derefnode(iptree
, np
->ipnode
);
154 /* TODO: figure out how to cleanly remove nodes without affecting other modules */
156 /* Delete the nick from the servernick table */
157 *(gethandlebynumericunsafe(np
->numeric
))=NULL
;
159 /* Remove the nick from the hash table */
160 removenickfromhash(np
);
165 void addnicktohash(nick
*np
) {
166 np
->next
=nicktable
[nickhash(np
->nick
)];
167 nicktable
[nickhash(np
->nick
)]=np
;
170 void removenickfromhash(nick
*np
) {
173 for (nh
=&(nicktable
[nickhash(np
->nick
)]);*nh
;nh
=&((*nh
)->next
)) {
181 nick
*getnickbynick(const char *name
) {
184 for (np
=nicktable
[nickhash(name
)];np
;np
=np
->next
) {
185 if (!ircd_strcmp(np
->nick
,name
))
192 void nickstats(int hooknum
, void *arg
) {
193 int total
,maxchain
,curchain
,i
,buckets
;
198 buckets
=total
=maxchain
=curchain
=0;
199 for (i
=0;i
<NICKHASHSIZE
;i
++,curchain
=0) {
203 for (;np
;np
=np
->next
) {
208 if (curchain
>maxchain
) {
215 sprintf(buf
,"Nick : %6d nicks (HASH: %6d/%6d, chain %3d)",total
,buckets
,NICKHASHSIZE
,maxchain
);
216 } else if ((long)arg
>2) {
217 sprintf(buf
,"Nick : %6d users on network.",total
);
221 triggerhook(HOOK_CORE_STATSREPLY
,buf
);
225 int registernickext(const char *name
) {
228 if (findnickext(name
)!=-1) {
229 Error("nick",ERR_WARNING
,"Tried to register duplicate nick extension %s",name
);
233 for (i
=0;i
<MAXNICKEXTS
;i
++) {
234 if (nickextnames
[i
]==NULL
) {
235 nickextnames
[i
]=getsstring(name
,100);
240 Error("nick",ERR_WARNING
,"Tried to register too many nick extensions: %s",name
);
244 int findnickext(const char *name
) {
247 for (i
=0;i
<MAXNICKEXTS
;i
++) {
248 if (nickextnames
[i
]!=NULL
&& !ircd_strcmp(name
,nickextnames
[i
]->content
)) {
256 void releasenickext(int index
) {
260 freesstring(nickextnames
[index
]);
261 nickextnames
[index
]=NULL
;
263 for (i
=0;i
<NICKHASHSIZE
;i
++) {
264 for (np
=nicktable
[i
];np
;np
=np
->next
) {
265 np
->exts
[index
]=NULL
;
270 int registerauthnameext(const char *name
) {
273 if (findauthnameext(name
)!=-1) {
274 Error("nick",ERR_WARNING
,"Tried to register duplicate authname extension %s",name
);
278 for (i
=0;i
<MAXAUTHNAMEEXTS
;i
++) {
279 if (authnameextnames
[i
]==NULL
) {
280 authnameextnames
[i
]=getsstring(name
,100);
285 Error("nick",ERR_WARNING
,"Tried to register too many authname extensions: %s",name
);
289 int findauthnameext(const char *name
) {
292 for (i
=0;i
<MAXAUTHNAMEEXTS
;i
++) {
293 if (authnameextnames
[i
]!=NULL
&& !ircd_strcmp(name
,authnameextnames
[i
]->content
)) {
301 void releaseauthnameext(int index
) {
305 freesstring(authnameextnames
[index
]);
306 authnameextnames
[index
]=NULL
;
308 for (i
=0;i
<AUTHNAMEHASHSIZE
;i
++) {
309 for (anp
=authnametable
[i
];anp
;anp
=anp
->next
) {
310 anp
->exts
[index
]=NULL
;
316 * Produces the "apparent" hostmask as seen by network users.
319 char *visiblehostmask(nick
*np
, char *buf
) {
320 char hostbuf
[HOSTLEN
+1];
324 host
=np
->host
->name
->content
;
328 ident
=np
->shident
->content
;
331 host
=np
->sethost
->content
;
333 } else if (IsAccount(np
) && IsHideHost(np
)) {
334 sprintf(hostbuf
,"%s.%s", np
->authname
, HIS_HIDDENHOST
);
338 sprintf(buf
,"%s!%s@%s",np
->nick
,ident
,host
);
346 * gethandlebynumeric:
347 * Given a numeric, gives the location in the servernicks table
348 * where it should be. Does not check that the nick currently found
349 * there (if any) has the correct numeric; this is left to the
350 * calling function to figure out.
353 nick
**gethandlebynumeric(long numeric
) {
358 /* Shift off the client identifier part of the numeric to get the server ID */
359 servernum
=(numeric
>>18);
361 if ((serv
=getserverdata(servernum
))==NULL
) {
362 Error("nick",ERR_WARNING
,"Numeric %ld refers to non-existent server %d",numeric
,servernum
);
366 /* Compute the masked numeric */
367 maskednum
=numeric
&(serv
->maxusernum
);
369 return (servernicks
[servernum
])+maskednum
;
373 * getnickbynumeric[str]()
374 * These functions retrieve a nick based on it's numeric on the network
375 * Use the approriate function depending on how your numeric is expressed..
378 nick
*getnickbynumeric(long numeric
) {
381 nh
=gethandlebynumeric(numeric
);
383 if ((*nh
) && ((*nh
)->numeric
!=numeric
)) {
384 /* We found a masked numeric match, but the actual numeric
385 * is different. This counts as a miss. */
392 nick
*getnickbynumericstr(char *numericstr
) {
393 return getnickbynumeric(numerictolong(numericstr
,5));
398 int registernodeext(const char *name
) {
401 if (findnodeext(name
)!=-1) {
402 Error("nick",ERR_WARNING
,"Tried to register duplicate node extension %s",name
);
406 for (i
=0;i
<PATRICIA_MAXSLOTS
;i
++) {
407 if (nodeextnames
[i
]==NULL
) {
408 nodeextnames
[i
]=getsstring(name
,100);
413 Error("nick",ERR_WARNING
,"Tried to register too many extensions: %s",name
);
417 int findnodeext(const char *name
) {
420 for (i
=0;i
<PATRICIA_MAXSLOTS
;i
++) {
421 if (nodeextnames
[i
]!=NULL
&& !ircd_strcmp(name
,nodeextnames
[i
]->content
)) {
429 void releasenodeext(int index
) {
430 patricia_node_t
*head
, *node
;
432 freesstring(nodeextnames
[index
]);
433 nodeextnames
[index
]=NULL
;
437 PATRICIA_WALK_ALL(head
, node
)
439 node
->slots
[index
]=NULL
;