]> jfr.im git - irc/quakenet/newserv.git/blame - authext/authext.c
Use nsmalloc/nsfree for authext.
[irc/quakenet/newserv.git] / authext / authext.c
CommitLineData
57583275 1#include "authext.h"
2#include "../core/nsmalloc.h"
3#include "../core/error.h"
4#include "../lib/sstring.h"
5#include "../lib/irc_string.h"
5a335041 6#include "../nick/nick.h"
d40ae845 7#include "../core/hooks.h"
1a96a370 8#include "../lib/strlfunc.h"
240bbd21 9#include "../lib/version.h"
57583275 10
11#include <string.h>
d40ae845 12#include <stdio.h>
57583275 13
240bbd21
CP
14MODULE_VERSION("")
15
57583275 16#define authnamehash(x) ((x)%AUTHNAMEHASHSIZE)
5a335041 17#define authnamehashbyname(x) (crc32i(x)%AUTHNAMEHASHSIZE)
57583275 18
57583275 19authname *authnametable[AUTHNAMEHASHSIZE];
20
5a335041
CP
21/* internal access only */
22static authname *authnametablebyname[AUTHNAMEHASHSIZE];
23
04b12064
CP
24static struct {
25 sstring *name;
bbf9de81 26 int persistent;
04b12064 27} authnameexts[MAXAUTHNAMEEXTS];
57583275 28
d40ae845
CP
29static void authextstats(int hooknum, void *arg);
30
5a335041 31void _init(void) {
57583275 32 memset(authnametable,0,sizeof(authnametable));
5a335041 33 memset(authnametablebyname,0,sizeof(authnametablebyname));
d40ae845 34 registerhook(HOOK_CORE_STATSREQUEST, &authextstats);
57583275 35}
36
5a335041 37void _fini(void) {
d40ae845 38 deregisterhook(HOOK_CORE_STATSREQUEST, &authextstats);
57583275 39 nsfreeall(POOL_AUTHEXT);
40}
41
5a335041 42authname *newauthname(void) {
be78a174 43 return nsmalloc(POOL_AUTHEXT, sizeof(authname));
57583275 44}
45
46void freeauthname (authname *anp) {
be78a174 47 nsfree(POOL_AUTHEXT, anp);
57583275 48}
49
bbf9de81 50int registerauthnameext(const char *name, int persistent) {
57583275 51 int i;
52
53 if (findauthnameext(name)!=-1) {
54 Error("nick",ERR_WARNING,"Tried to register duplicate authname extension %s",name);
55 return -1;
56 }
57
58 for (i=0;i<MAXAUTHNAMEEXTS;i++) {
04b12064
CP
59 if (authnameexts[i].name==NULL) {
60 authnameexts[i].name=getsstring(name,100);
bbf9de81 61 authnameexts[i].persistent=persistent;
57583275 62 return i;
63 }
64 }
65
66 Error("nick",ERR_WARNING,"Tried to register too many authname extensions: %s",name);
67 return -1;
68}
69
70int findauthnameext(const char *name) {
71 int i;
72
73 for (i=0;i<MAXAUTHNAMEEXTS;i++) {
04b12064 74 if (authnameexts[i].name!=NULL && !ircd_strcmp(name,authnameexts[i].name->content)) {
57583275 75 return i;
76 }
77 }
78
79 return -1;
80}
81
82void releaseauthnameext(int index) {
83 int i;
84 authname *anp;
85
04b12064
CP
86 freesstring(authnameexts[index].name);
87 authnameexts[index].name=NULL;
57583275 88
89 for (i=0;i<AUTHNAMEHASHSIZE;i++) {
90 for (anp=authnametable[i];anp;anp=anp->next) {
91 anp->exts[index]=NULL;
92 }
93 }
5a335041
CP
94
95 /* the contents of authnametablebyname should be identical */
57583275 96}
97
98authname *findauthname(unsigned long userid) {
99 authname *anp;
100
101 if(!userid)
102 return NULL;
103
104 for (anp=authnametable[authnamehash(userid)];anp;anp=(authname *)anp->next)
105 if (userid==anp->userid)
106 return anp;
107
108 return NULL;
109}
110
5a335041 111authname *findauthnamebyname(const char *name) {
57583275 112 authname *anp;
57583275 113
5a335041
CP
114 if(!name)
115 return NULL;
116
d40ae845 117 for (anp=authnametablebyname[authnamehashbyname(name)];anp;anp=(authname *)anp->nextbyname)
1a96a370 118 if (!ircd_strcmp(anp->name, name))
5a335041
CP
119 return anp;
120
121 return NULL;
122}
123
124authname *findorcreateauthname(unsigned long userid, const char *name) {
125 authname *anp;
126 unsigned int thehash=authnamehash(userid), secondhash = authnamehashbyname(name);
127
128 if(!userid || !name)
57583275 129 return NULL;
130
131 for (anp=authnametable[thehash];anp;anp=(authname *)anp->next)
132 if (userid==anp->userid)
133 return anp;
134
135 anp=newauthname();
136 anp->userid=userid;
1a96a370 137 strlcpy(anp->name, name, sizeof(anp->name));
57583275 138 anp->usercount=0;
139 anp->marker=0;
0b0fb773 140 anp->flags=0;
57583275 141 anp->nicks=NULL;
142 memset(anp->exts, 0, MAXAUTHNAMEEXTS * sizeof(void *));
143 anp->next=(struct authname *)authnametable[thehash];
144 authnametable[thehash]=anp;
145
5a335041
CP
146 anp->namebucket=secondhash;
147 anp->nextbyname=(struct authname *)authnametablebyname[secondhash];
148 authnametablebyname[secondhash]=anp;
149
57583275 150 return anp;
151}
152
153void releaseauthname(authname *anp) {
154 authname **manp;
5a335041 155 int i, found;
57583275 156 if (anp->usercount==0) {
1cf62143
CP
157 anp->nicks = NULL;
158
57583275 159 for(i=0;i<MAXAUTHNAMEEXTS;i++)
bbf9de81 160 if(authnameexts[i].persistent && anp->exts[i]!=NULL)
57583275 161 return;
162
04b12064 163 triggerhook(HOOK_AUTH_LOSTAUTHNAME, (void *)anp);
5a335041 164 found = 0;
57583275 165 for(manp=&(authnametable[authnamehash(anp->userid)]);*manp;manp=(authname **)&((*manp)->next)) {
5a335041
CP
166 if ((*manp)==anp) {
167 (*manp)=(authname *)anp->next;
168 found = 1;
169 break;
170 }
171 }
172 if(!found) {
173 Error("nick",ERR_ERROR,"Unable to remove authname %lu from hashtable",anp->userid);
174 return;
175 }
176
4884107a 177 for(manp=&(authnametablebyname[anp->namebucket]);*manp;manp=(authname **)&((*manp)->nextbyname)) {
57583275 178 if ((*manp)==anp) {
4884107a 179 (*manp)=(authname *)anp->nextbyname;
57583275 180 freeauthname(anp);
181 return;
182 }
183 }
5a335041 184
4884107a 185 Error("nick",ERR_STOP,"Unable to remove authname %lu from byname hashtable, TABLES ARE INCONSISTENT -- DYING",anp->userid);
57583275 186 }
187}
188
5a335041 189unsigned int nextauthnamemarker(void) {
57583275 190 int i;
191 authname *anp;
192 static unsigned int authnamemarker=0;
193
194 authnamemarker++;
195 if (!authnamemarker) {
196 /* If we wrapped to zero, zap the marker on all records */
197 for (i=0;i<AUTHNAMEHASHSIZE;i++)
198 for (anp=authnametable[i];anp;anp=anp->next)
199 anp->marker=0;
200 authnamemarker++;
201 }
202
203 return authnamemarker;
204}
1cf62143
CP
205
206authname *getauthbyname(const char *name) {
207 authname *a = findauthnamebyname(name);
208 if(!a || !a->nicks)
209 return NULL;
210
211 return a;
212}
213
cdc9e13c 214static char *genstats(authname **hashtable, authname *(nextfn)(authname *)) {
d40ae845
CP
215 int i,curchain,maxchain=0,total=0,buckets=0;
216 authname *ap;
217 static char buf[100];
218
219 for (i=0;i<AUTHNAMEHASHSIZE;i++) {
220 if (hashtable[i]!=NULL) {
221 buckets++;
222 curchain=0;
cdc9e13c 223 for (ap=hashtable[i];ap;ap=nextfn(ap)) {
d40ae845
CP
224 total++;
225 curchain++;
226 }
227 if (curchain>maxchain) {
228 maxchain=curchain;
229 }
230 }
231 }
232
233 snprintf(buf, sizeof(buf), "%6d authexts (HASH: %6d/%6d, chain %3d)",total,buckets,AUTHNAMEHASHSIZE,maxchain);
234 return buf;
235}
236
cdc9e13c
CP
237static authname *nextbynext(authname *in) {
238 return in->next;
239}
240
241static authname *nextbyname(authname *in) {
242 return in->nextbyname;
243}
244
d40ae845
CP
245static void authextstats(int hooknum, void *arg) {
246 long level=(long)arg;
247 char buf[100];
248
249 if (level>5) {
250 /* Full stats */
cdc9e13c 251 snprintf(buf,sizeof(buf),"Authext : by id: %s", genstats(authnametable, nextbynext));
d40ae845
CP
252 triggerhook(HOOK_CORE_STATSREPLY,buf);
253
cdc9e13c 254 snprintf(buf,sizeof(buf),"Authext : by name: %s", genstats(authnametablebyname, nextbyname));
d40ae845
CP
255 triggerhook(HOOK_CORE_STATSREPLY,buf);
256 }
257}
258