]>
jfr.im git - irc/quakenet/newserv.git/blob - nick/nick.c
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"
15 #include "../lib/ccassert.h"
16 #include "../core/nsmalloc.h"
24 CCASSERT(sizeof(host
) == sizeof(realname
));
26 const flag umodeflags
[] = {
28 { 'w', UMODE_WALLOPS
},
31 { 'k', UMODE_SERVICE
},
34 { 'r', UMODE_ACCOUNT
},
35 { 'n', UMODE_HIDECHAN
},
36 { 'x', UMODE_HIDEHOST
},
37 { 'h', UMODE_SETHOST
},
38 { 'R', UMODE_REGPRIV
},
39 { 'I', UMODE_HIDEIDLE
},
40 { 'P', UMODE_PARANOID
},
41 { 'q', UMODE_COMCHANS
},
42 { 'Q', UMODE_COMCHANSRESTR
},
43 { 'C', UMODE_CLOAKED
},
46 const flag accountflags
[] = {
48 { 'h', AFLAG_SUPPORT
},
51 { 'd', AFLAG_DEVELOPER
},
54 #define nickhash(x) ((irc_crc32i(x))%NICKHASHSIZE)
56 nick
*nicktable
[NICKHASHSIZE
];
57 nick
**servernicks
[MAXSERVERS
];
59 sstring
*nickextnames
[MAXNICKEXTS
];
61 void nickstats(int hooknum
, void *arg
);
63 char *NULLAUTHNAME
= "";
69 /* Clear up the nicks in authext */
70 for (i
=0;i
<AUTHNAMEHASHSIZE
;i
++)
71 for (anp
=authnametable
[i
];anp
;anp
=anp
->next
)
75 memset(nicktable
,0,sizeof(nicktable
));
76 memset(servernicks
,0,sizeof(servernicks
));
78 /* If we're connected to IRC, force a disconnect. This needs to be done
79 * before we register all our hooks which would otherwise get called
80 * during the disconnect. */
82 irc_send("%s SQ %s 0 :Resync [adding nick support]",mynumeric
->content
,myserver
->content
); irc_disconnected(0);
85 /* Register our hooks */
86 registerhook(HOOK_SERVER_NEWSERVER
,&handleserverchange
);
87 registerhook(HOOK_SERVER_LOSTSERVER
,&handleserverchange
);
88 registerhook(HOOK_CORE_STATSREQUEST
,&nickstats
);
90 /* And our server handlers */
91 registerserverhandler("N",&handlenickmsg
,10);
92 registerserverhandler("D",&handlekillmsg
,2);
93 registerserverhandler("Q",&handlequitmsg
,1);
94 registerserverhandler("M",&handleusermodemsg
,3);
95 registerserverhandler("AC",&handleaccountmsg
,4);
96 registerserverhandler("P",&handleprivmsg
,2);
97 registerserverhandler("A",&handleawaymsg
,1);
98 registerserverhandler("CA",&handleaddcloak
,1);
99 registerserverhandler("CU",&handleclearcloak
,0);
101 /* Fake the addition of our own server */
102 handleserverchange(HOOK_SERVER_NEWSERVER
,(void *)numerictolong(mynumeric
->content
,2));
111 for (i
=0;i
<NICKHASHSIZE
;i
++) {
112 for (np
=nicktable
[i
];np
;np
=np
->next
) {
113 freesstring(np
->shident
);
114 freesstring(np
->sethost
);
115 freesstring(np
->opername
);
116 if(!np
->auth
&& np
->authname
&& (np
->authname
!= NULLAUTHNAME
))
121 nsfreeall(POOL_NICK
);
124 deregisterhook(HOOK_SERVER_NEWSERVER
,&handleserverchange
);
125 deregisterhook(HOOK_SERVER_LOSTSERVER
,&handleserverchange
);
126 deregisterhook(HOOK_CORE_STATSREQUEST
,&nickstats
);
128 /* And our server handlers */
129 deregisterserverhandler("N",&handlenickmsg
);
130 deregisterserverhandler("D",&handlekillmsg
);
131 deregisterserverhandler("Q",&handlequitmsg
);
132 deregisterserverhandler("M",&handleusermodemsg
);
133 deregisterserverhandler("AC",&handleaccountmsg
);
134 deregisterserverhandler("P",&handleprivmsg
);
135 deregisterserverhandler("A",&handleawaymsg
);
136 deregisterserverhandler("CA",&handleaddcloak
);
137 deregisterserverhandler("CU",&handleclearcloak
);
141 * This function handles servers appearing and disappearing.
142 * For a new server, the client table is allocated.
143 * For a disappearing server, all it's clients are killed and the client table is freed.
146 void handleserverchange(int hooknum
, void *arg
) {
153 case HOOK_SERVER_NEWSERVER
:
154 servernicks
[servernum
]=(nick
**)nsmalloc(POOL_NICK
,(serverlist
[servernum
].maxusernum
+1)*sizeof(nick
**));
155 memset(servernicks
[servernum
],0,(serverlist
[servernum
].maxusernum
+1)*sizeof(nick
**));
158 case HOOK_SERVER_LOSTSERVER
:
159 for (i
=0;i
<=serverlist
[servernum
].maxusernum
;i
++) {
160 if (servernicks
[servernum
][i
]!=NULL
) {
161 deletenick(servernicks
[servernum
][i
]);
164 nsfree(POOL_NICK
,servernicks
[servernum
]);
172 * This function handles the removal of a nick from the network
175 void deletenick(nick
*np
) {
178 /* Fire a pre-lostnick trigger to allow hooks to check the channels etc. of a lost nick */
179 triggerhook(HOOK_NICK_PRE_LOSTNICK
, np
);
181 /* Fire the hook. This will deal with removal from channels etc. */
182 triggerhook(HOOK_NICK_LOSTNICK
, np
);
184 /* Release the realname and hostname parts */
186 for (nh
=&(np
->realname
->nicks
);*nh
;nh
=&((*nh
)->nextbyrealname
)) {
188 *nh
=np
->nextbyrealname
;
193 for (nh
=&(np
->host
->nicks
);*nh
;nh
=&((*nh
)->nextbyhost
)) {
200 releaserealname(np
->realname
);
201 releasehost(np
->host
);
205 if(np
->authname
&& (np
->authname
!= NULLAUTHNAME
))
208 np
->auth
->usercount
--;
210 for (nh
=&(np
->auth
->nicks
);*nh
;nh
=&((*nh
)->nextbyauthname
)) {
212 *nh
=np
->nextbyauthname
;
217 releaseauthname(np
->auth
);
221 freesstring(np
->shident
); /* freesstring(NULL) is OK */
222 freesstring(np
->sethost
);
223 freesstring(np
->opername
);
224 freesstring(np
->message
);
226 node_decrement_usercount(np
->ipnode
);
227 derefnode(iptree
, np
->ipnode
);
229 /* TODO: figure out how to cleanly remove nodes without affecting other modules */
231 /* Remove cloak entries for the user */
232 removecloaktarget(np
);
233 clearcloaktargets(np
);
235 /* Delete the nick from the servernick table */
236 *(gethandlebynumericunsafe(np
->numeric
))=NULL
;
238 /* Remove the nick from the hash table */
239 removenickfromhash(np
);
244 void addnicktohash(nick
*np
) {
245 np
->next
=nicktable
[nickhash(np
->nick
)];
246 nicktable
[nickhash(np
->nick
)]=np
;
249 void removenickfromhash(nick
*np
) {
252 for (nh
=&(nicktable
[nickhash(np
->nick
)]);*nh
;nh
=&((*nh
)->next
)) {
260 nick
*getnickbynick(const char *name
) {
263 for (np
=nicktable
[nickhash(name
)];np
;np
=np
->next
) {
264 if (!ircd_strcmp(np
->nick
,name
))
271 void nickstats(int hooknum
, void *arg
) {
272 int total
,maxchain
,curchain
,i
,buckets
;
277 buckets
=total
=maxchain
=curchain
=0;
278 for (i
=0;i
<NICKHASHSIZE
;i
++,curchain
=0) {
282 for (;np
;np
=np
->next
) {
287 if (curchain
>maxchain
) {
294 sprintf(buf
,"Nick : %6d nicks (HASH: %6d/%6d, chain %3d)",total
,buckets
,NICKHASHSIZE
,maxchain
);
295 } else if ((long)arg
>2) {
296 sprintf(buf
,"Nick : %6d users on network.",total
);
300 triggerhook(HOOK_CORE_STATSREPLY
,buf
);
304 int registernickext(const char *name
) {
307 if (findnickext(name
)!=-1) {
308 Error("nick",ERR_WARNING
,"Tried to register duplicate nick extension %s",name
);
312 for (i
=0;i
<MAXNICKEXTS
;i
++) {
313 if (nickextnames
[i
]==NULL
) {
314 nickextnames
[i
]=getsstring(name
,100);
319 Error("nick",ERR_WARNING
,"Tried to register too many nick extensions: %s",name
);
323 int findnickext(const char *name
) {
326 for (i
=0;i
<MAXNICKEXTS
;i
++) {
327 if (nickextnames
[i
]!=NULL
&& !ircd_strcmp(name
,nickextnames
[i
]->content
)) {
335 void releasenickext(int index
) {
339 freesstring(nickextnames
[index
]);
340 nickextnames
[index
]=NULL
;
342 for (i
=0;i
<NICKHASHSIZE
;i
++) {
343 for (np
=nicktable
[i
];np
;np
=np
->next
) {
344 np
->exts
[index
]=NULL
;
350 * Produces the "apparent" hostmask as seen by network users.
353 char *visiblehostmask(nick
*np
, char *buf
) {
354 char uhbuf
[USERLEN
+HOSTLEN
+2];
356 visibleuserhost(np
, uhbuf
);
357 sprintf(buf
,"%s!%s",np
->nick
,uhbuf
);
363 * As above without nick
366 char *visibleuserhost(nick
*np
, char *buf
) {
367 char hostbuf
[HOSTLEN
+1];
371 host
=np
->host
->name
->content
;
375 ident
=np
->shident
->content
;
378 host
=np
->sethost
->content
;
380 } else if (IsAccount(np
) && IsHideHost(np
)) {
381 sprintf(hostbuf
,"%s.%s", np
->authname
, HIS_HIDDENHOST
);
385 sprintf(buf
,"%s@%s",ident
,host
);
393 * gethandlebynumeric:
394 * Given a numeric, gives the location in the servernicks table
395 * where it should be. Does not check that the nick currently found
396 * there (if any) has the correct numeric; this is left to the
397 * calling function to figure out.
400 nick
**gethandlebynumeric(long numeric
) {
405 /* Shift off the client identifier part of the numeric to get the server ID */
406 servernum
=(numeric
>>18);
408 if ((serv
=getserverdata(servernum
))==NULL
) {
409 Error("nick",ERR_WARNING
,"Numeric %ld refers to non-existent server %d",numeric
,servernum
);
413 /* Compute the masked numeric */
414 maskednum
=numeric
&(serv
->maxusernum
);
416 return (servernicks
[servernum
])+maskednum
;
420 * getnickbynumeric[str]()
421 * These functions retrieve a nick based on it's numeric on the network
422 * Use the approriate function depending on how your numeric is expressed..
425 nick
*getnickbynumeric(long numeric
) {
428 nh
=gethandlebynumeric(numeric
);
430 if ((*nh
) && ((*nh
)->numeric
!=numeric
)) {
431 /* We found a masked numeric match, but the actual numeric
432 * is different. This counts as a miss. */
439 nick
*getnickbynumericstr(char *numericstr
) {
440 return getnickbynumeric(numerictolong(numericstr
,5));
446 int canseeuser(nick
*np
, nick
*cloaked
)
448 return (np
== cloaked
||
449 !IsCloaked(cloaked
) ||
450 np
->cloak_extra
== cloaked
);
453 void addcloaktarget(nick
*cloaked
, nick
*target
)
455 removecloaktarget(target
);
457 target
->cloak_extra
= cloaked
;
458 cloaked
->cloak_count
++;
461 void removecloaktarget(nick
*target
)
463 if (target
->cloak_extra
) {
464 target
->cloak_extra
->cloak_count
--;
465 target
->cloak_extra
= NULL
;
469 void clearcloaktargets(nick
*cloaked
)
474 if (cloaked
->cloak_count
== 0)
477 for(j
=0;j
<NICKHASHSIZE
;j
++)
478 for(tnp
=nicktable
[j
];tnp
;tnp
=tnp
->next
)
479 if (tnp
->cloak_extra
== cloaked
)
480 tnp
->cloak_extra
= NULL
;
482 cloaked
->cloak_count
= 0;