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